Skip to content

v0.8: docs/LIFE_BINDING_SPEC.md + schemas/binding.schema.json + sanity tests (#103)#111

Merged
LING71671 merged 5 commits into
masterfrom
devin/1777217754-103-life-binding-spec
Apr 26, 2026
Merged

v0.8: docs/LIFE_BINDING_SPEC.md + schemas/binding.schema.json + sanity tests (#103)#111
LING71671 merged 5 commits into
masterfrom
devin/1777217754-103-life-binding-spec

Conversation

@devin-ai-integration
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot commented Apr 26, 2026

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 for
    binding/runtime_binding.json (dlrs-life-binding/0.1).
    patternProperties enforce both the capability-name hybrid
    vocabulary AND the hard-constraints hybrid keyspace;
    additionalProperties: false makes unknown non-x- keys reject
    statically (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: false boundary. Wired into
    tools/batch_validate.py.
  • CHANGELOG.md — v0.8 (Draft) gains a Binding entry next to
    Genesis.

Decisions encoded (Topic 3 + cross-topic)

# Decision Schema realisation
D1=C Hybrid capability vocabulary capabilities.patternProperties core enum + x- extension regex; everything else rejected.
D2=C Issuer-self-decided engine strictness engine_entry.strict boolean (default true).
D3 → tier system Replaced by tier (#104) capability_binding.tier_floor references it; full definition lives in [#104].
D4=C Hybrid hard_constraints + fail-close hard_constraints.patternProperties ~30 core keys + x-; additionalProperties: false.
D5=A AND-gate hosted-API decision hosted_api_preference (issuer half) + policy/hosted_api.json (user half); default-deny when section omitted.
Topic 4 D4=C Three-field surface shape supported / preferred / minimum_required.

Local validation

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.

  • Skim docs/LIFE_BINDING_SPEC.md end-to-end and confirm the
    four locked Topic-3 decisions are encoded faithfully
    (especially D4=C fail-close and D5=A default-deny semantics).
  • Spot-check the core capability enum (~20 names) and the core
    hard_constraints keys (~30 names) against the realistic
    vocabulary you want — both lists are intentionally hard to
    shrink later but easy to extend.
  • Confirm surface_mode ordering (text_only < chat < voice_chat < avatar_2d < avatar_3d < vr) matches your mental
    model of "render-capability requirements".

Notes

Link to Devin session: https://app.devin.ai/sessions/ff7322e18fd94887875daa2c1c75f87d
Requested by: @LING71671


Open in Devin Review

…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-integration
Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
devin-ai-integration[bot]

This comment was marked as resolved.

LING71671 and others added 2 commits April 26, 2026 15:53
…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>
devin-ai-integration[bot]

This comment was marked as resolved.

… 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>
Copy link
Copy Markdown
Contributor Author

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 8 additional findings in Devin Review.

Open in Devin Review

Comment on lines +189 to +190
"avatar_image_ref": { "type": "string", "minLength": 1 },
"background_audio_ref": { "type": "string", "minLength": 1 }
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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).

Suggested change
"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": "^(?!/)(?!.*\\.\\.).+$" }
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@LING71671 LING71671 merged commit ce2e7b6 into master Apr 26, 2026
5 checks passed
devin-ai-integration Bot added a commit that referenced this pull request Apr 26, 2026
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
LING71671 added a commit that referenced this pull request Apr 26, 2026
…777219690-followup-ui-hints-path-traversal

fix(.life): binding ui_hints _ref fields path-traversal pattern (post-#111 review)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

v0.8: docs/LIFE_BINDING_SPEC.md + schemas/binding.schema.json + sanity tests

1 participant