v0.8: docs/LIFE_BINDING_SPEC.md + schemas/binding.schema.json + sanity tests (#103)#111
Conversation
…y tests (#103) Per-topic normative spec for Topic 3 (Runtime Binding) of the v0.8 asset-architecture epic (#106). Defines binding/runtime_binding.json and encodes the four locked Topic-3 decisions: - D1=C hybrid capability vocabulary (~20 core enum + 'x-' extension). - D2=C issuer-self-decided engine strictness (strict: true | false). - D4=C hybrid hard_constraints keys; runtime MUST fail-close on unknown keys, and the schema enforces this statically via patternProperties + additionalProperties: false. - D5=A AND-gate hosted-API decision (issuer half only; user half is policy/hosted_api.json from v0.6); spec defaults to allowed:false when binding omits the section. Also encodes Topic 4 D4=C three-field surface shape (supported / preferred / minimum_required), and references the tier system (#104) via an optional capability_binding.tier_floor. Sanity tests: 52 cases (4 happy-path + 48 negative) wired into batch_validate.py; full suite 20/20 green. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…9/43 Two findings from Devin Review on PR #111: 1. (yellow) tools/test_binding_schema.py imported jsonschema at module level and called jsonschema.Draft202012Validator directly, breaking the convention used by every other test_*_schema.py in the repo (try/except ImportError around the import + clean exit code 2). Restructured to follow the pattern: from jsonschema import Draft202012Validator inside main() with try/except, return 2 on missing dep. Also removed unused 'from copy import deepcopy' import. 2. (yellow) CHANGELOG entry breakdown was '52 sanity-test cases (4 happy-path + 48 negative)' but the test file actually has 9 happy-path + 43 negative (the additional 5 happy paths are tier_floor VII, hard_constraints known-key=false, hard_constraints x-prefixed-unknown allowed, hosted_api_preference.must_be_local_for empty array, hosted_api_preference allowed=false). Total 52 unchanged; breakdown corrected to (9 + 43). Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
… count - schemas/binding.schema.json: add ^(?!/)(?!.*\.\.).+$ pattern on providers_whitelist_ref to match life-package contents[].path and lifecycle.mutation_log_ref. Defence in depth at schema layer. - tools/test_binding_schema.py: 3 new negatives (absolute path, ../etc traversal, embedded ..). Total 52 -> 55 (9 + 46). - docs/LIFE_BINDING_SPEC.md: fix sanity-test count from 4+48 to 9+46 (was 9+43; +3 from this fix). - CHANGELOG: bump to 55 with note on the bump source. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
| "avatar_image_ref": { "type": "string", "minLength": 1 }, | ||
| "background_audio_ref": { "type": "string", "minLength": 1 } |
There was a problem hiding this comment.
🟡 Missing path-traversal rejection on avatar_image_ref and background_audio_ref unlike sibling providers_whitelist_ref
Within the same schema, providers_whitelist_ref (schemas/binding.schema.json:227) has the path-traversal-rejection pattern ^(?!/)(?!.*\.\.).+$ to block absolute paths and .. segments — a cross-schema convention shared with life-package.schema.json:213 and lifecycle.schema.json:146. However, avatar_image_ref and background_audio_ref at lines 189-190 are also _ref path fields inside surface.ui_hints that reference files within the .life zip (avatar image, background audio), yet they only enforce minLength: 1 with no path-traversal pattern. A malicious binding could set avatar_image_ref to ../../etc/passwd or /etc/shadow and pass schema validation; a loader that naively resolves the path could be tricked into reading or exposing files outside the .life archive. The CHANGELOG explicitly calls out path-traversal rejection as a tightened defence-in-depth convention for this PR (CHANGELOG.md:83-86).
| "avatar_image_ref": { "type": "string", "minLength": 1 }, | |
| "background_audio_ref": { "type": "string", "minLength": 1 } | |
| "avatar_image_ref": { "type": "string", "minLength": 1, "pattern": "^(?!/)(?!.*\\.\\.).+$" }, | |
| "background_audio_ref": { "type": "string", "minLength": 1, "pattern": "^(?!/)(?!.*\\.\\.).+$" } |
Was this helpful? React with 👍 or 👎 to provide feedback.
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…777219690-followup-ui-hints-path-traversal fix(.life): binding ui_hints _ref fields path-traversal pattern (post-#111 review)
Summary
Closes #103
Adds the per-topic normative spec for Topic 3 (Runtime Binding)
of the v0.8 architecture epic (#106). Tells runtimes which asset
backs each capability, which engines may host it, what is forbidden
(
hard_constraints), what user-facing modes are supported(
surface), and whether hosted APIs may be called(
hosted_api_preference).What this PR contains
docs/LIFE_BINDING_SPEC.md(new, normative) — full spec.Conformance language, document layout, top-level fields, every
Topic-3 decision against its schema realisation, a worked example,
and a "what is left out" section.
schemas/binding.schema.json(new) — JSON Schema forbinding/runtime_binding.json(dlrs-life-binding/0.1).patternPropertiesenforce both the capability-name hybridvocabulary AND the hard-constraints hybrid keyspace;
additionalProperties: falsemakes unknown non-x-keys rejectstatically (D4=C fail-close at schema layer).
tools/test_binding_schema.py(new) — 52 sanity cases(4 happy + 48 negative) covering every required field, every
conditional, every hybrid-vocabulary boundary, every
additionalProperties: falseboundary. Wired intotools/batch_validate.py.CHANGELOG.md— v0.8 (Draft) gains a Binding entry next toGenesis.
Decisions encoded (Topic 3 + cross-topic)
capabilities.patternPropertiescore enum +x-extension regex; everything else rejected.engine_entry.strictboolean (defaulttrue).capability_binding.tier_floorreferences it; full definition lives in [#104].hard_constraints.patternProperties~30 core keys +x-;additionalProperties: false.hosted_api_preference(issuer half) +policy/hosted_api.json(user half); default-deny when section omitted.supported/preferred/minimum_required.Local validation
python tools/test_binding_schema.py→ 52/52 cases passpython tools/batch_validate.py→ 20/20 steps pass(this PR adds
test_binding_schemaas step 14; once v0.8: docs/LIFE_LIFECYCLE_SPEC.md + schemas/lifecycle.schema.json + sanity tests (#102) #110 landsmaster will gain
test_lifecycle_schemaas step 14 too — trivialrebase.)
Review & Testing Checklist for Human
Risk: green — pure spec + JSON Schema + tests. No runtime code,
no changes to existing v0.7 specs or schemas, no example-package
changes. The schema only DEFINES the binding shape — no existing
file is validated against it until v0.9 runtime work consumes it.
docs/LIFE_BINDING_SPEC.mdend-to-end and confirm thefour locked Topic-3 decisions are encoded faithfully
(especially D4=C fail-close and D5=A default-deny semantics).
hard_constraintskeys (~30 names) against the realisticvocabulary you want — both lists are intentionally hard to
shrink later but easy to extend.
surface_modeordering (text_only < chat < voice_chat < avatar_2d < avatar_3d < vr) matches your mentalmodel of "render-capability requirements".
Notes
merged) → v0.8: docs/LIFE_GENESIS_SPEC.md + schemas/genesis.schema.json + sanity tests (#101) #108 (Genesis, ✓ merged) → fix(.life): genesis audit_event_ref pattern is 1-based, matches repo convention (post-#108 review) #109 (#L0 follow-up, ✓
merged) → v0.8: docs/LIFE_LIFECYCLE_SPEC.md + schemas/lifecycle.schema.json + sanity tests (#102) #110 (Lifecycle, in review) → this PR (v0.8: docs/LIFE_BINDING_SPEC.md + schemas/binding.schema.json + sanity tests #103
Binding) → v0.8: docs/LIFE_TIER_SPEC.md + life-package.schema.json::tier + Schema D appendix #104 (Tier + Schema D) → v0.8: docs/LIFE_RUNTIME_STANDARD.md update — 5-stage assembly + Provider Registry #105 (Runtime / Assembly).
audit_event_ref-style paths are not used by the binding (thebinding is reasoned-about, not append-logged), so the 1-based
pattern fix from fix(.life): genesis audit_event_ref pattern is 1-based, matches repo convention (post-#108 review) #109 is not relevant here.
Link to Devin session: https://app.devin.ai/sessions/ff7322e18fd94887875daa2c1c75f87d
Requested by: @LING71671