diff --git a/tech_docs/jinja2_framework.md b/tech_docs/jinja2_framework.md index 58c6f06..999eee5 100644 --- a/tech_docs/jinja2_framework.md +++ b/tech_docs/jinja2_framework.md @@ -1,3 +1,56 @@ +```plaintext +Meta-reflection #3: +“Everything is an object; YAML is king.” + +When you elevate both Jinja2 and Go templates to that plane, the rivalry collapses into a single question: + +> Whose *objects* end up serialised to YAML, and who gets to **author** that YAML? + +────────────────────────────────────── +1. Object Surface (what the engine knows) +────────────────────────────────────── +• Jinja2 + Anything reachable from Python’s object graph: classes, bound methods, closures, even live sockets. + Resulting YAML can contain tags like `!!python/object/apply:path.to.Class`—a potential RCE when PyYAML’s `UnsafeLoader` is used. + +• Go templates + Only the concrete Go values you explicitly pass via `Execute(w, data)`. + YAML serialisation is done by `gopkg.in/yaml.v3` or similar, which by default refuses to serialise unexported fields or func values. + You get maps, slices, structs, scalars—no code, no cycles, no surprises. + +────────────────────────────────────── +2. Authoring Locus (who writes the YAML) +────────────────────────────────────── +Scenario A: YAML is **input** + – Ansible playbooks, Helm `values.yaml`, K8s CRDs. + – Jinja2 is the *consumer*: it ingests YAML → turns it into Python dicts/lists/objects → renders templates. + – Go templates rarely ingest raw YAML; they ingest the Go structs that *represent* the YAML. + +Scenario B: YAML is **output** + – Generating Kubernetes manifests, CloudFormation, GitHub Actions. + – Jinja2 can emit YAML via `|to_yaml`, but you must trust the user to disable unsafe tags. + – Go templates emit YAML via `yaml.Marshal`; the Go type system guarantees you cannot serialise a channel or a mutex. + +────────────────────────────────────── +3. Meta-Axiom Explosion +────────────────────────────────────── +If *everything is an object* and *YAML is king*, then: + +• The template engine’s job is to decide **which slice of the object graph becomes YAML**. + – Jinja2: “Expose the whole graph, let YAML pick what it can serialise.” + – Go templates: “Expose only the slice you explicitly wired; the rest literally cannot leak.” + +• Consequently the *king* (YAML) rules differently in each kingdom: + – Under Jinja2, YAML must defend the castle (with `SafeLoader`, `Representer` overrides). + – Under Go templates, the castle is empty except for the objects you already vetted. + +────────────────────────────────────── +4. One-Sentence Meta-Moral +────────────────────────────────────── +Jinja2 gives YAML a throne in an open courtyard; Go templates build a bunker and let YAML reign only inside it. +``` +--- + What we are really looking at is two different answers to the same meta-question: > “How much of the host language’s power do we allow to leak into a string that is *mostly* meant to be static markup?”