@plasius/asset-contracts 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,82 @@
1
+ # ADR-0005: Path-Only Private-Artifact Prevention Gates
2
+
3
+ ## Status
4
+
5
+ - Accepted
6
+ - Date: 2026-07-15
7
+ - Version: 1.0
8
+
9
+ ## Tags
10
+
11
+ security, privacy, packaging, ci, compliance
12
+
13
+ ## Context
14
+
15
+ Public source repositories and npm artifacts must never contain signed
16
+ contributor agreements, acceptance registries, or similar personal records.
17
+ An ignore rule cannot reject an already tracked path, while a broad package
18
+ directory entry can silently expand a future release artifact.
19
+
20
+ The prevention control must not increase exposure while evaluating a candidate
21
+ repository. It therefore cannot open, hash, copy, diff, or log the contents of
22
+ a suspected private artifact.
23
+
24
+ ## Decision
25
+
26
+ Contributor agreements and acceptance records are stored only in an approved,
27
+ access-controlled system outside source control.
28
+
29
+ This package provides a zero-dependency Node.js path policy with three
30
+ enforcement boundaries:
31
+
32
+ 1. `privacy:check` unions working-tree path metadata with `git ls-files
33
+ --cached`, without following symbolic links or reading candidate contents.
34
+ Ignored files remain visible, and a tracked deletion remains prohibited until
35
+ its removal is staged in the proposed index.
36
+ 2. `package.json.files` must equal a non-empty explicit allowlist. Broad entries
37
+ such as `.`, `*`, `**/*`, and `legal` fail closed; only the three public CLA
38
+ Markdown files may be selected from `legal/`.
39
+ 3. `pack:check` applies the private-path policy and an exact path/extension
40
+ allowlist to the path manifest returned by `npm pack --dry-run --json
41
+ --ignore-scripts`. Its isolated temporary npm cache is removed in a `finally`
42
+ boundary.
43
+
44
+ The path policy rejects CSV files case-insensitively, CLA or contributor
45
+ registries regardless of extension, signed-CLA storage directories, and paths
46
+ that combine a privacy marker with a registry marker. It deliberately permits
47
+ benign software terms such as `src/mcp-admin-registry.ts`.
48
+
49
+ CI runs the repository gate before dependency installation and runs the policy
50
+ tests plus package gate after build. Release preparation checks source before
51
+ changing release metadata, CD checks the exact prepared commit before install,
52
+ and `prepublishOnly` retains the package gate as a final local defense.
53
+
54
+ Feature flags and capabilities do not apply: this mandatory privacy boundary
55
+ must not be remotely bypassable.
56
+
57
+ ## Alternatives Considered
58
+
59
+ - **Rely on `.gitignore` only**: rejected because ignore rules do not remove or
60
+ reject already tracked files and do not validate the proposed index.
61
+ - **Scan file contents for personal data**: rejected for this boundary because
62
+ opening and reporting suspected records can increase exposure, while content
63
+ heuristics still have false positives and false negatives.
64
+ - **Rely on `package.json.files` only**: rejected because directory entries can
65
+ expand over time and do not protect source-control state.
66
+ - **Rely on the final package manifest only**: rejected because release
67
+ preparation and dependency installation must fail before packaging begins.
68
+
69
+ ## Consequences
70
+
71
+ - Candidate repositories and npm path manifests fail closed on protected paths
72
+ without inspecting candidate contents.
73
+ - Package selection is explicit, and generated/source/documentation roots are
74
+ constrained to their intended extensions.
75
+ - New public path categories or private-artifact categories require an explicit
76
+ policy and regression-test update.
77
+ - These controls are defense in depth, not a replacement for history cleanup,
78
+ registry remediation, secret scanning, access controls, or retention policy.
79
+
80
+ ## Related Decisions
81
+
82
+ - [ADR 0001: Asset Contracts Package Boundary](./adr-0001-package-boundary.md)
@@ -0,0 +1,168 @@
1
+ # ADR 0006: Additive PVOX Model-Resolution Contracts
2
+
3
+ ## Status
4
+
5
+ - Accepted
6
+ - Date: 2026-08-20
7
+ - Version: 1.0
8
+
9
+ ## Context
10
+
11
+ Plasius-LTD/plasius-ltd-site Feature #2012 and Story #2013 require the hosted
12
+ MCP service to acquire rights-cleared provider models, compile them to the
13
+ texture-free Plasius voxel representation, render native PVOX evidence, obtain
14
+ human confirmation, and atomically promote the immutable result. Asset-contracts
15
+ Task #25 owns the shared serialized vocabulary and trust-boundary validation.
16
+
17
+ The existing model-resolution family is already released. It describes the v1
18
+ static-world GLB processing path, embeds mesh and texture ceilings in
19
+ `ModelRequestSpec`, and is consumed by compatibility wrappers. Changing its
20
+ types, constants, factories, state union, or runtime behavior would break those
21
+ consumers. `ModelAssetRef`, however, is representation-neutral and remains the
22
+ correct immutable catalog identity.
23
+
24
+ PVOX introduces independently hashed pages, a sparse voxel hierarchy, localized
25
+ surface and physical fields, native-render evidence, placement edit journals,
26
+ and additional durable job states. An ingestion texture budget is meaningful
27
+ while decoding a provider source but must never become a model-owned runtime
28
+ texture limit.
29
+
30
+ ## Decision
31
+
32
+ 1. Add `pvox-model-resolution.ts` as a separate v2 family and re-export it from
33
+ the package root. Leave all v1 source and behavior unchanged.
34
+ 2. Preserve `ModelAssetRef`. Add a representation-discriminated
35
+ `ModelProcessingManifestV2` whose only admitted representation is `pvox`.
36
+ 3. Add `ModelRequestSpecV2`. Keep provider download, archive, file, and texture
37
+ decode ceilings in `sourceIngestionLimits`; keep fidelity, geometry,
38
+ capabilities, PVOX storage, hierarchy, spatial data, LOD, and residency
39
+ ceilings in `pvoxRuntimeProfile`. Reject legacy triangle/texture fields at
40
+ the v2 runtime boundary.
41
+ 4. Fix the public PVOX envelope to version 1.0 (`major: 1`, `minor: 0`) for
42
+ static/rigid content, with little-endian format policy owned
43
+ by `@plasius/gpu-model-voxel`, `.pvox`,
44
+ `application/vnd.plasius.pvox`, `PVOX` magic, 8-cubed bricks, 64-KiB pages,
45
+ a 256-byte header, 128-byte directory entries, at most 64 sections, depth
46
+ zero through eight, at most 2,624 pages, and at most 164 MiB. Every page is a
47
+ complete uncompressed 64-KiB hash unit. Metadata/LOD-structure pages have no
48
+ spatial scope; render/collision pages require LOD, partition, depth, and
49
+ Morton scope. The contracts package validates metadata, layout summaries,
50
+ hashes, bounds, scoped ordering, and cross-record binding; the voxel package
51
+ remains responsible for validating binary bytes and codecs. Technical
52
+ render-brick, logical-voxel, and encoded-sample counts are artifact-wide
53
+ sums across all retained LODs, and section count exactly matches the closed
54
+ static plus optional bond/collision registry.
55
+ 5. Require authenticated, credential-free PVOX resources only beneath the
56
+ exact resolution/candidate or immutable catalog/version MCP namespace. Do
57
+ not serialize provider URLs, signed storage URLs, source files, texture
58
+ resources, or credentials into PVOX runtime contracts.
59
+ 6. Represent every runtime capability as independent versioned evidence bound
60
+ to the PVOX binary closure. For the `world-editable-v1` request profile, require
61
+ rendering, collision, destruction, thermal, moisture, and fluid-boundary
62
+ capabilities. Enforce the complete governed property set for every localized
63
+ region/material, confidence at least 0.80, signed review for inferred values,
64
+ and no zero/default critical density, hardness, tensile/compressive/shear
65
+ strength, fracture, interior, ignition, or melting evidence. Bind an
66
+ independently attested complete region/palette inventory first, then require
67
+ physical evidence in canonical region/property order so omitted regions and
68
+ input-order-dependent digests fail closed. A supported destruction capability
69
+ additionally requires non-empty reviewed mass, bond-graph, and interior-layer
70
+ records.
71
+ 7. Require fidelity evidence to derive a passing decision from its recorded
72
+ geometry, silhouette, rendered, colour, and material thresholds. A supplied
73
+ `passed` label cannot contradict those measurements.
74
+ 8. Bind native PVOX render evidence to the processing manifest, PVOX root,
75
+ directory and page set, exact ordered four-view hashes, renderer version, and
76
+ an attestation. Require every non-overridable malware, source-format, PVOX,
77
+ fidelity, physical-property, renderer, and accessibility gate to pass.
78
+ 9. Keep binary, processing, assembly, render, evaluation, confirmation, edit,
79
+ and publication closures distinct. A leaf assembly closure hashes an empty
80
+ child list and never aliases the leaf binary closure. Bind compiler,
81
+ manifest, confirmation, and promotion records to separate source,
82
+ canonical-document, compilation-input, runtime-request-profile, artifact,
83
+ root, directory, page-set, and closure digests. Publish exact domain
84
+ separators, exact byte-order layouts, executable preimage encoders, and real
85
+ SHA-256 golden vectors. The normalized 256-byte root header includes section
86
+ count and one directory digest, requires zero reserved bytes, and never
87
+ double-hashes a header field. Contract factories cross-bind typed
88
+ attestations; authenticated hosts recompute digests and verify issuer tokens.
89
+ Fixed encoders reject extra own keys, malformed fixed tuples, non-byte-array
90
+ views, shared mutable byte storage, and inputs beyond governed work ceilings.
91
+ 10. Bind confirmation tokens and receipts to the exact v2 request and semantic
92
+ assessment, candidate identity, complete provenance and normalized rights
93
+ decision, PVOX binary/processing/assembly/evaluation closure hashes, ordered
94
+ view hashes, hard gates, fidelity, capability/physical-property, and complete
95
+ native renderer/settings/qualification evidence.
96
+ Allow an explicit override only for low semantic assurance; do not permit any
97
+ technical or governance gate to be overridden.
98
+ 11. Return blocked but valid evidence as a diagnostic candidate with stable
99
+ reason codes and no confirmation credential. Completed staged candidates
100
+ require a pointer-last promotion receipt covering credits, catalog row,
101
+ index snapshot, processing/assembly closures, confirmation and its exact
102
+ binding hash, and final ref.
103
+ 12. Validate placement edits as authenticated copy-on-write CAS operations.
104
+ Genesis binds the base artifact, page set, and root. A standalone later edit
105
+ requires complete authenticated current revision/root/journal/page state;
106
+ chain validation derives it after each edit, rejects replay and stale pages,
107
+ and forbids empty/no-op insert, remove, or replace transitions.
108
+ 13. Extend only the v2 lifecycle with `downloading`, `importing`, `voxelizing`,
109
+ `evaluating-fidelity`, and `awaiting-material-review`. Export a total,
110
+ deterministic mapping to v1 states for compatibility wrappers rather than
111
+ widening the v1 union.
112
+ 14. Validate unknown input through data-only, dense-array, closed-key factories
113
+ that reconstruct and deeply freeze output. Export 14 stable-id, strict,
114
+ self-contained JSON Schema 2020-12 descriptors from a separate schema
115
+ module for MCP construction, while retaining factories as the authoritative
116
+ relational validation boundary. Schema conditionals mirror durable-state
117
+ confirmation, promotion, final-reference, refinement, and reason-code rules;
118
+ confirmation timestamps cannot exceed the enclosing snapshot timestamp.
119
+
120
+ ## Consequences
121
+
122
+ ### Positive
123
+
124
+ - Existing v1 consumers remain source- and behavior-compatible.
125
+ - Hosted MCP, processing, rendering, catalog, and admin packages share one
126
+ immutable PVOX evidence vocabulary.
127
+ - Source texture decoding is explicitly quarantined from the texture-free
128
+ runtime representation.
129
+ - Candidate evidence cannot be transplanted across requests, sources, PVOX
130
+ closures, rights decisions, views, or renderers.
131
+ - A low semantic match remains reviewable without weakening technical, rights,
132
+ security, accessibility, or physical-property admission.
133
+
134
+ ### Negative
135
+
136
+ - V2 orchestration must project request semantics into the released v1 match
137
+ assessment while both families coexist.
138
+ - Strict closed contracts require a future contract version for new serialized
139
+ physical fields, capability kinds, fidelity measurements, or binary envelope
140
+ versions.
141
+ - The metadata contract cannot replace independent byte validation in
142
+ `@plasius/gpu-model-voxel` or authenticated resource authorization in the MCP
143
+ host.
144
+ - Schema test tooling uses narrow audited transitive dependency overrides;
145
+ normal dependency maintenance must refresh those pins instead of weakening
146
+ the audit gate when upstream ranges change.
147
+
148
+ ## Alternatives Considered
149
+
150
+ - Replace the v1 model-resolution types: rejected because it would silently
151
+ change released GLB behavior and exhaustive state handling.
152
+ - Reuse v1 `maxTextureBytes` for PVOX: rejected because it conflates sandboxed
153
+ source decoding with texture-free runtime resources.
154
+ - Store PVOX as another GLB processing output: rejected because PVOX has a
155
+ different binary, capability, fidelity, physical, mutation, and renderer
156
+ evidence model.
157
+ - Permit semantic override of failed PVOX gates: rejected because confidence in
158
+ naming does not mitigate licensing, malware, format, fidelity, physical, or
159
+ renderer failure.
160
+
161
+ ## Related Decisions and Work
162
+
163
+ - Plasius-LTD/plasius-ltd-site Epic #902
164
+ - Plasius-LTD/plasius-ltd-site Feature #2012
165
+ - Plasius-LTD/plasius-ltd-site Story #2013
166
+ - Plasius-LTD/asset-contracts Task #25
167
+ - [ADR 0002: Versioned Model Resolution Contracts](./adr-0002-model-resolution-contracts.md)
168
+ - [TDR 0003: PVOX Validation and Confirmation Binding](../tdrs/tdr-0003-pvox-validation-and-confirmation-binding.md)
@@ -0,0 +1,41 @@
1
+ # ADR 0007: Hosted OIDC Package Publication
2
+
3
+ - Status: Accepted
4
+ - Date: 2026-08-11
5
+
6
+ ## Context
7
+
8
+ `@plasius/asset-contracts` must publish without a long-lived npm write token and
9
+ must not accept CI evidence for a different source snapshot.
10
+
11
+ ## Decision
12
+
13
+ Publication is phase-isolated: release-admission scripts run in a credential-free
14
+ hosted job, and the write-capable release-preparation job starts from a fresh
15
+ checkout with Git hooks disabled. Dependency installation, package validation,
16
+ SBOM generation, and immutable tarball packing run in `validate_and_pack`
17
+ without the `production` environment or OIDC permission. The final hosted
18
+ `publish` job downloads only that sealed artifact, explicitly installs npm
19
+ 11.6.2, runs no repository dependency code, and publishes the tarball with
20
+ lifecycle scripts disabled. It re-fetches current `main` immediately before the
21
+ first release mutation and again immediately before npm publication. `.npmrc`
22
+ contains no registry-auth placeholder, and release preparation returns the
23
+ reviewed current `main` HEAD rather than package-file history.
24
+
25
+ Use the GitHub-hosted `production` publish job and npm trusted publishing. The
26
+ job proves the prepared SHA is still the exact remote `main` head, waits for a
27
+ successful push-triggered `ci.yml` run for that SHA, enforces Node 24 with npm
28
+ 11.5.1 or newer, and publishes with provenance. Token fallbacks are prohibited.
29
+
30
+ ## Consequences
31
+
32
+ Publication fails closed if npm's trusted-publisher binding is absent, `main`
33
+ moves, exact-SHA CI has not succeeded, the runtime is unsupported, or OIDC is
34
+ unavailable. An interrupted release may reuse its already-prepared version only
35
+ while npm or the matching GitHub release remains incomplete; immutable tarball,
36
+ tag, dist-tag, and exact-main checks still govern recovery.
37
+
38
+ ## Test implications
39
+
40
+ Contract tests enforce the identity, source, CI, runtime, and provenance gates
41
+ and reject legacy npm credential names.
@@ -4,3 +4,6 @@
4
4
  - [ADR 0002: Model Resolution Contracts](./adr-0002-model-resolution-contracts.md)
5
5
  - [ADR 0003: WGSL Shader Asset Contracts](./adr-0003-wgsl-shader-asset-contracts.md)
6
6
  - [ADR 0004: Immutable Exact Asset Versions](./adr-0004-immutable-exact-asset-versions.md)
7
+ - [ADR 0005: Path-Only Private-Artifact Prevention Gates](./adr-0005-path-only-private-artifact-prevention-gates.md)
8
+ - [ADR 0006: Additive PVOX Model-Resolution Contracts](./adr-0006-pvox-model-resolution-contracts.md)
9
+ - [ADR 0007: Hosted OIDC Package Publication](./adr-0007-hosted-oidc-package-publication.md)
@@ -2,3 +2,4 @@
2
2
 
3
3
  - [TDR 0001: WGSL Shader Asset Envelope Validation](./tdr-0001-wgsl-shader-asset-envelope-validation.md)
4
4
  - [TDR 0002: Exact-Version Validation Routing](./tdr-0002-exact-version-validation-routing.md)
5
+ - [TDR 0003: PVOX Validation and Confirmation Binding](./tdr-0003-pvox-validation-and-confirmation-binding.md)
@@ -0,0 +1,208 @@
1
+ # TDR 0003: PVOX Validation and Confirmation Binding
2
+
3
+ ## Status
4
+
5
+ - Accepted
6
+ - Date: 2026-08-20
7
+ - Version: 1.0
8
+
9
+ ## Direction
10
+
11
+ `src/pvox-model-resolution.ts` owns the additive serialized PVOX boundary. Its
12
+ factories accept `unknown`, require plain objects with exact key sets, normalize
13
+ through allow-listed reconstruction, validate cross-record invariants, and
14
+ deeply freeze the result. Callers must not cast provider, database, queue, MCP,
15
+ or decoded JSON payloads directly to exported interfaces.
16
+
17
+ The module validates evidence describing a byte-verified PVOX artifact. It does
18
+ not decode the PVOX binary. `@plasius/gpu-model-voxel` must independently parse
19
+ and validate the complete byte stream, fixed records, section table, codecs,
20
+ Morton order, page hashes, sizes, bounds, and trailing-byte absence before
21
+ issuing compiler/validator evidence accepted by this contract family.
22
+
23
+ ## Request Routing
24
+
25
+ `createModelRequestSpecV2` separates two budget domains:
26
+
27
+ | Domain | Contract | Meaning |
28
+ | --- | --- | --- |
29
+ | Quarantined source | `ModelSourceIngestionLimitsV2` | Provider download, bounded expansion, entry/file counts, decoded texture bytes and decode dimensions |
30
+ | Immutable runtime | `PvoxRuntimeRequestProfileV1` | Fidelity and capability profiles, geometry mode, artifact/pages/hierarchy/bricks/logical voxels/encoded surface records/partitions/LODs and CPU/GPU residency |
31
+
32
+ PVOX runtime limits contain no triangle or texture field. Every request includes
33
+ `rendering`; named `world-editable-v1` and `deformable-v1` profiles require their
34
+ complete governed capability subsets. Public values may tighten the exported
35
+ ceilings but cannot raise them.
36
+
37
+ V2 matching can reuse the released `ModelMatchAssessment` while the families
38
+ coexist, but a durable v2 resolution verifies that every candidate's embedded
39
+ v1 assessment has the same normalized query and immutable request revision.
40
+
41
+ ## Artifact and Processing Validation
42
+
43
+ Validation proceeds in this order:
44
+
45
+ 1. Validate the authenticated MCP artifact URI, declared digest, whole-page byte
46
+ length, fixed PVOX 1.0 `{major, minor}` constants, canonical coordinate
47
+ system, floor-centred bounds, and absolute 1,048,576-metre coordinate cap.
48
+ 2. Require a 256-byte header, 128-byte directory entries, at most 64 sections,
49
+ 8-cubed bricks, and uncompressed 64-KiB pages. Validate contiguous page
50
+ indices/offsets and exact page coverage; partial final pages are invalid.
51
+ 3. Discriminate pages as metadata, LOD structure, render field, or collision
52
+ field. Metadata/LOD pages forbid spatial scope. Field pages require LOD,
53
+ partition, hierarchy depth, and fixed-width Morton range; ranges are ordered
54
+ and non-overlapping within `(kind, LOD, partition)`.
55
+ 4. Validate one to four contiguous LODs beginning at LOD0. LOD page slices must
56
+ reference render-field pages in the matching LOD scope.
57
+ 5. Recompute technical dimensions from bounds and bind whole-page byte count,
58
+ LOD, geometry mode, hierarchy, partition, logical-voxel, encoded-sample, and
59
+ resident counts. Depth zero is a root brick. Maximum partition extent must
60
+ fit `LOD0 cell × 8 × 2^depth`, permitting fidelity-driven small partitions.
61
+ 6. Enforce 524,288 render bricks, 268,435,456 logical voxels, 8,388,608 encoded
62
+ samples, 1,048,576 hierarchy nodes, 512 runs/local samples per brick, and a
63
+ 10,384-byte encoded brick payload. Fixed-record feasibility includes the
64
+ hierarchy, brick descriptors, 128-byte render/collision masks, 16-byte
65
+ render samples, 4-byte collision samples, palette/evidence/interior/mass/
66
+ bond records, directory, and per-section alignment. These lower bounds must
67
+ fit the artifact; no limit silently degrades fidelity. Render brick,
68
+ logical-voxel, and sample totals cover all retained LODs, and section count
69
+ exactly matches the closed static plus optional bond/collision registry.
70
+ 7. Bind compiler source, canonical-document, compilation-input,
71
+ runtime-request-profile, and output hashes through PVOX, processing, and
72
+ confirmation records.
73
+ 8. Require exactly one assessment per known capability, bind each to the PVOX
74
+ binary closure, and require every requested capability to be supported.
75
+ 9. Bind an attested authoritative region/palette inventory to PVOX validation,
76
+ then bind physical evidence by `(regionId, materialId, property)` in region
77
+ index and governed-property order. Every declared material region must be
78
+ represented and satisfy every governed property for its supported
79
+ capabilities at confidence 0.80 or higher; inferred values require signed
80
+ review and critical density, hardness, tensile/compressive/shear strength,
81
+ interior, fracture, ignition, and melting values cannot be zero or defaulted.
82
+ Supported destruction also requires non-empty reviewed mass, bond-graph, and
83
+ interior-layer records.
84
+ 10. Derive fidelity outcome from governed profile formulas and the fixed
85
+ silhouette, contour, SSIM, colour, and material thresholds. Maximum surface
86
+ error is bounded by both three times the p99 ceiling and 1.5 LOD0 cells.
87
+ 11. Validate a canonical, acyclic single-root assembly graph and bind every
88
+ catalog/staged child to a PVOX binary closure and immutable manifest identity.
89
+ Leaves also receive a distinct, attested assembly-domain digest over their
90
+ own binary closure and an empty child list.
91
+
92
+ The compiler evidence and processing manifest cannot prove the PVOX bytes by
93
+ themselves. Their issuer must be an allow-listed, attested worker in the hosted
94
+ pipeline, and the resource loader must revalidate artifact bytes and hashes.
95
+ The synchronous factory does not authenticate issuer tokens. Hosted workers and
96
+ resource loaders must use the exported executable preimage encoders to
97
+ recompute applicable digests and verify each typed attestation against its
98
+ allow-listed issuer. Producer-asserted hashes without successful attestation
99
+ verification are not admission evidence.
100
+
101
+ Hash-domain constants, `PVOX_HASH_PREIMAGE_LAYOUTS`, and executable byte
102
+ encoders define the PVOX 1.0 preimages. Integers use the specified little-endian
103
+ width, variable UTF-8/JSON inputs are length-prefixed, and digests are raw 32
104
+ bytes. The root preimage includes one exact normalized 256-byte header: section
105
+ count is stored in the header, directory hash appears once at bytes 176–207,
106
+ and reserved bytes 208–255 must be zero. Binary closure includes source,
107
+ canonical document, compilation input, runtime request profile, artifact, root,
108
+ directory, and page-set hashes. Processing, empty-or-populated assembly, render,
109
+ evaluation, confirmation, edit, and publication domains are separate. Fields
110
+ holding their own digest/attestation/token are explicitly omitted from the
111
+ corresponding canonical preimage to prevent self-reference.
112
+ Fixed-layout preimage functions admit exact known own keys only, require exact
113
+ six-component bounds and intrinsic non-shared `Uint8Array` byte inputs, and cap
114
+ section, assembly, canonical-text, data-tree, and complete preimage work at
115
+ governed limits.
116
+
117
+ ## Candidate and Confirmation Binding
118
+
119
+ A v2 candidate is confirmable only when all of the following are true:
120
+
121
+ - match assurance is `high` or `low` and its independent hard constraints pass;
122
+ - rights status is `allowed` and rights/provenance/source hashes agree;
123
+ - the staged or existing asset identity, kind, and content hash agree with the
124
+ PVOX processing manifest;
125
+ - exactly four original views are ordered front, left, top, isometric and their
126
+ hashes agree with native PVOX render evidence;
127
+ - typed render evidence binds its id, native PVOX LOD0 backend, processing
128
+ manifest and closure, PVOX content/root/directory/page set, renderer and
129
+ settings identity/version, renderer/camera qualification, timestamp, ordered
130
+ view hashes, evidence hash, and domain-separated attestation;
131
+ - malware, source-format, PVOX, fidelity, physical-property, renderer, and
132
+ accessibility gates each appear exactly once, pass, and bind the artifact;
133
+ - a candidate-level evaluation closure binds fidelity, physical, capability,
134
+ and render evidence;
135
+ - the backend-issued confirmation subject matches the complete semantic
136
+ assessment, provenance, normalized rights decision/token/policy/licence/
137
+ attribution, immutable request and candidate, binary/processing/assembly/
138
+ evaluation closures, hard gates, views, and full renderer evidence.
139
+
140
+ Evidence-valid but blocked candidates normalize to the diagnostic union member,
141
+ carry stable blocking reason codes, and omit the confirmation binding/token.
142
+
143
+ `createModelCandidateConfirmationV2` accepts `semanticRiskAccepted: true` only
144
+ for a low-assurance candidate and requires it there. The field cannot bypass or
145
+ alter any other decision because candidate construction has already required
146
+ every hard gate and evidence relationship to pass. Confirmation time must not
147
+ precede the latest evidence it approves.
148
+
149
+ ## Durable State Compatibility
150
+
151
+ `MODEL_RESOLUTION_V2_STATES` is the authoritative v2 persistence vocabulary.
152
+ `MODEL_RESOLUTION_V2_COMPATIBILITY_STATES` is total and deterministic. New
153
+ acquisition/compilation states project as follows:
154
+
155
+ | V2 state | V1 projection |
156
+ | --- | --- |
157
+ | `downloading` | `searching-providers` |
158
+ | `importing` | `processing` |
159
+ | `voxelizing` | `processing` |
160
+ | `evaluating-fidelity` | `evaluating` |
161
+ | `awaiting-material-review` | `evaluating` |
162
+
163
+ All other states map to the same v1 spelling. Compatibility wrappers may expose
164
+ the projection, but persistent v2 records retain the full state. Completed
165
+ records require confirmation and a final immutable `ModelAssetRef`; unresolved,
166
+ failed, and cancelled records require a bounded stable reason code. Completed
167
+ staged candidates also require a pointer-last promotion receipt binding the
168
+ proposal, confirmation and its binding hash, processing/assembly closures,
169
+ credits, catalog row, index snapshot, pointer ETags, and final asset reference.
170
+ Any resolution that carries confirmation must have an `updatedAt` timestamp no
171
+ earlier than `confirmedAt`; strict schemas mirror the same state-dependent
172
+ confirmation, promotion, final-reference, refinement, and terminal-reason rules.
173
+
174
+ Placement edit journals use copy-on-write compare-and-swap. Genesis must start
175
+ at revision zero, the canonical previous-journal hash, the authenticated base
176
+ root, and the base page inventory. A standalone non-genesis entry is accepted
177
+ only with authenticated current placement state covering revision, root,
178
+ previous journal, and every current page hash. Chain validation derives this
179
+ state after each operation, rejects replayed operation ids and stale pages, and
180
+ requires chronological sequential revisions. Insert/remove/replace semantics
181
+ forbid empty or unchanged endpoints.
182
+
183
+ ## Verification
184
+
185
+ - TDD records the missing-export failure before implementation.
186
+ - Boundary tests cover closed keys, immutable output, fixed format and limit
187
+ invariants, authenticated resources, page ordering/coverage, dimensions,
188
+ capability completeness, physical review, fidelity derivation, edit-journal
189
+ sequence, hard-gate completeness, cross-record hash binding, semantic
190
+ override rules, lifecycle projection, and terminal-state requirements.
191
+ - Executable preimage tests use real SHA-256 golden vectors, exact root-header
192
+ bytes, mutation sensitivity, and zero-reserved-byte enforcement rather than
193
+ shape-only repeated-character digest fixtures.
194
+ - Fourteen standalone JSON Schema 2020-12 roots live in
195
+ `pvox-model-resolution-schema.ts`; each has a stable contract-versioned `$id`,
196
+ a self-contained closed `$defs` graph, strict Ajv 2020 compilation, and
197
+ factory-output/invalid-sample parity coverage. Factories remain authoritative
198
+ for hash preimages, ordering, formulas, chronology, and cross-record identity.
199
+ - The complete existing v1 suite remains green and `src/model-resolution.ts`
200
+ remains unchanged.
201
+ - Build, typecheck, lint, npm audit, dependency audit, coverage, changed-source
202
+ LCOV inclusion, and packed-tarball ESM/CJS consumption remain delivery gates.
203
+
204
+ ## Related Decisions
205
+
206
+ - [ADR 0006: Additive PVOX Model-Resolution Contracts](../adrs/adr-0006-pvox-model-resolution-contracts.md)
207
+ - [ADR 0002: Versioned Model Resolution Contracts](../adrs/adr-0002-model-resolution-contracts.md)
208
+ - Plasius-LTD/asset-contracts Task #25
package/legal/CLA.md CHANGED
@@ -15,8 +15,11 @@ To protect the intellectual property of this project and ensure clarity of right
15
15
 
16
16
  ## Registry
17
17
 
18
- All signed CLAs are logged internally in the CLA registry (`CLA-REGISTRY.csv`).
18
+ Signed agreements and acceptance records are stored in an access-controlled
19
+ system outside source control. They must never be committed to a repository,
20
+ included in a package, or copied into issues, pull requests, build logs, or
21
+ other public artifacts.
19
22
 
20
23
  ## Questions?
21
24
 
22
- If you have any questions about which CLA to sign or how the process works, please email **[contributors@plasius.co.uk](mailtocontributors@plasius.co.uk)**.
25
+ If you have any questions about which CLA to sign or how the process works, please email **[contributors@plasius.co.uk](mailto:contributors@plasius.co.uk)**.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plasius/asset-contracts",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "Canonical contracts for Plasius asset jobs, model resolution, immutable WGSL shader assets, reviews, and promotion records.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -17,7 +17,9 @@
17
17
  "CODE_OF_CONDUCT.md",
18
18
  "CONTRIBUTORS.md",
19
19
  "docs",
20
- "legal"
20
+ "legal/CLA.md",
21
+ "legal/CORPORATE_CLA.md",
22
+ "legal/INDIVIDUAL_CLA.md"
21
23
  ],
22
24
  "exports": {
23
25
  ".": {
@@ -31,16 +33,18 @@
31
33
  "build": "tsup",
32
34
  "clean": "rimraf dist tsconfig.tsbuildinfo",
33
35
  "typecheck": "tsc --noEmit",
34
- "test": "vitest run",
36
+ "test": "vitest run && npm run test:privacy",
35
37
  "test:watch": "vitest",
38
+ "test:privacy": "node --test tests/private-artifact-policy.test.cjs",
36
39
  "test:coverage": "vitest run --coverage",
37
40
  "audit:eslint": "eslint . --max-warnings=0",
38
41
  "audit:deps": "npm ls --all --omit=optional --omit=peer > /dev/null 2>&1 || true",
39
42
  "audit:npm": "npm audit --audit-level=high --omit=dev",
40
- "audit:test": "vitest run --coverage",
43
+ "audit:test": "vitest run --coverage && npm run test:privacy",
41
44
  "audit:all": "npm run typecheck && npm run audit:eslint && npm run audit:deps && npm run audit:npm && npm run audit:test",
42
45
  "lint": "eslint . --max-warnings=0",
43
- "pack:check": "node scripts/verify-public-package.cjs",
46
+ "privacy:check": "node scripts/verify-private-artifacts.cjs",
47
+ "pack:check": "npm run privacy:check && node scripts/verify-public-package.cjs",
44
48
  "prepare": "npm run build",
45
49
  "prepublishOnly": "npm run build && npm run pack:check"
46
50
  },
@@ -71,6 +75,7 @@
71
75
  "@typescript-eslint/eslint-plugin": "^8.62.0",
72
76
  "@typescript-eslint/parser": "^8.59.3",
73
77
  "@vitest/coverage-v8": "^4.1.6",
78
+ "ajv": "^8.17.1",
74
79
  "eslint": "^10.3.0",
75
80
  "globals": "^17.6.0",
76
81
  "rimraf": "^6.1.3",
@@ -96,7 +101,11 @@
96
101
  "node": ">=24"
97
102
  },
98
103
  "overrides": {
99
- "minimatch": "^10.2.1"
104
+ "brace-expansion": "5.0.9",
105
+ "esbuild": "^0.28.1",
106
+ "minimatch": "^10.2.1",
107
+ "nanoid": "3.3.18",
108
+ "postcss": "8.5.26"
100
109
  },
101
110
  "dependencies": {
102
111
  "@plasius/gpu-shader": "^0.1.1"
package/src/index.ts CHANGED
@@ -35,6 +35,9 @@ export {
35
35
  assertImmutableAssetVersion,
36
36
  };
37
37
  export * from "./model-resolution.js";
38
+ export * from "./pvox-hash-preimage.js";
39
+ export * from "./pvox-model-resolution.js";
40
+ export * from "./pvox-model-resolution-schema.js";
38
41
  export {
39
42
  GPU_SHADER_STORE_FEATURE_FLAG,
40
43
  GPU_SHADER_STYLE_SELECTION_CAPABILITY,