mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-11-07 13:22:14 +00:00
TASK-6e4ff870-a386-4a11-a59c-444ebc23732e: add B1 fixture subject context
This commit is contained in:
1 parent
c08ca349c8
commit
9b4dfc7e97
4 files changed
+585
No files matched your search
@@ -2735,3 +2735,39 @@ test_integrity_note:
|
||||
did_relax_any_assertion: false
|
||||
if_true_explain_spec_basis: ""
|
||||
```
|
||||
|
||||
## 2026-10-01 — Check-subject context B1 fixture-only provenance boundary
|
||||
|
||||
```yaml
|
||||
test_integrity_note:
|
||||
change_type: new_tests
|
||||
scenarios:
|
||||
- id: SCN-check-subject-context-canonical-E-S-A
|
||||
given: Independently framed captured engine, subject, and adapter observations
|
||||
when: B1 canonicalizes and parses the bounded UTF-8/LF v1 payload
|
||||
then: Exact framed bytes and digest bind the three observations without treating product or engine content as framed bytes
|
||||
- id: SCN-check-subject-context-fixture-authority
|
||||
given: An issued fixture harness or copied, foreign, expired, and reused variants
|
||||
when: Fixture context admission or inspection is requested
|
||||
then: Only the issued single-use WeakMap authority succeeds, and its result remains nonpromotable, non-native, and receipt-ineligible
|
||||
- id: SCN-check-subject-context-schema-and-native-refusal
|
||||
given: Readable schema-2 legacy observations and no registered parent issuer
|
||||
when: A required-schema-3/current-schema-2 or otherwise registered v1 admission is requested
|
||||
then: The incompatibility or missing-composition refusal occurs with no ControlPlane, database, or write path
|
||||
observable_outcomes:
|
||||
- Exact public namespace allowlists and independent E/S/A preimage bytes
|
||||
- Refusal of selectors before parsing, V2-shaped fields, parent/native/loaded-engine claims, issued-object clones, drift, and repository-head relabeling
|
||||
- Fixture-only classification with no native candidate or receipt-like promotion surface
|
||||
- "V2 dependency-manifest, compatibility-declaration, snapshot-policy, and frozen-input-manifest bindings remain reserved for a separately reviewed version rather than being reinterpreted as V1"
|
||||
determinism_controls:
|
||||
- Fixed captured observations, independently assembled UTF-8/LF frames, private WeakMap authorities, and no network, provider, database, ControlPlane, retry, or sleep
|
||||
anti_cheat_rationale:
|
||||
prevents:
|
||||
- Minting registered authority through caller JSON, roots, callbacks, readers, verifiers, or selectors
|
||||
- Reinterpreting V1 fixture observations as a loaded engine, native parent binding, or V2 snapshot/dependency attestation
|
||||
- Promoting an isolated fixture result into a native candidate or PASS receipt
|
||||
- Inferring actual product, engine, or adapter bytes from repository HEAD or a mutable active pointer
|
||||
relaxation:
|
||||
did_relax_any_assertion: false
|
||||
if_true_explain_spec_basis: ""
|
||||
```
|
||||
@@ -0,0 +1,188 @@
|
||||
import { createHash, randomUUID } from 'node:crypto';
|
||||
import { TorchError } from './errors.mjs';
|
||||
import {
|
||||
canonicalManagedSubjectMetadataBytesV1,
|
||||
parseManagedSubjectMetadataV1,
|
||||
} from './managed-subject-metadata.mjs';
|
||||
|
||||
export const CHECK_SUBJECT_CONTEXT_PROTOCOL_VERSION = 1;
|
||||
|
||||
const harnesses = new WeakMap();
|
||||
const contexts = new WeakMap();
|
||||
const MUTATIONS = new Set([
|
||||
'engine-observation-drift', 'adapter-observation-drift', 'stale-subject-observation',
|
||||
'dirty-subject-claim', 'unknown-field', 'mixed-field', 'head-relabel',
|
||||
]);
|
||||
|
||||
function fail(message, code, details) {
|
||||
throw new TorchError(message, { code, details });
|
||||
}
|
||||
|
||||
function exactObject(value, allowed, label) {
|
||||
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
||||
fail(`${label} must be an object`, 'CHECK_SUBJECT_CONTEXT_INPUT_INVALID');
|
||||
}
|
||||
for (const key of Object.keys(value)) {
|
||||
if (!allowed.has(key)) fail(`${label} contains an unsupported field`, 'CHECK_SUBJECT_CONTEXT_INPUT_INVALID', { field: key });
|
||||
}
|
||||
}
|
||||
|
||||
function sha256(bytes) {
|
||||
return createHash('sha256').update(bytes).digest('hex');
|
||||
}
|
||||
|
||||
function frame(label, value) {
|
||||
const bytes = Buffer.from(value, 'utf8');
|
||||
return Buffer.concat([Buffer.from(`${label}:${bytes.length}\n`, 'ascii'), bytes, Buffer.from('\n', 'ascii')]);
|
||||
}
|
||||
|
||||
function fixtureObservations() {
|
||||
return {
|
||||
schema: 'torch.dev/managed-subject-metadata/v1alpha1',
|
||||
protocolVersion: 1,
|
||||
engine: { moduleId: 'candidate-engine', interfaceVersion: 1, byteLength: 4096, sha256: '1'.repeat(64) },
|
||||
subject: {
|
||||
projectId: 'fixture-project', productCommit: '2'.repeat(40), cleanTreeDigest: '3'.repeat(64),
|
||||
storageSchemaVersion: 2, storageSchemaDigest: '4'.repeat(64),
|
||||
},
|
||||
adapter: {
|
||||
moduleId: 'fixture-adapter', interfaceVersion: 1, byteLength: 2048, sha256: '5'.repeat(64),
|
||||
controlPlaneSchemaVersion: 2, compatibleStorageSchemaVersion: 2, compatibleStorageSchemaDigest: '4'.repeat(64),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function assertHarness(harness) {
|
||||
const state = harnesses.get(harness);
|
||||
if (!state) fail('Fixture authority is not issued by this module', 'CHECK_SUBJECT_CONTEXT_FIXTURE_AUTH_REQUIRED');
|
||||
if (state.closed) fail('Fixture authority has expired', 'CHECK_SUBJECT_CONTEXT_FIXTURE_AUTH_EXPIRED');
|
||||
return state;
|
||||
}
|
||||
|
||||
function assertContext(context) {
|
||||
const state = contexts.get(context);
|
||||
if (!state) fail('Fixture context is not issued by this module', 'CHECK_SUBJECT_CONTEXT_FIXTURE_AUTH_REQUIRED');
|
||||
if (state.closed) fail('Fixture context has expired', 'CHECK_SUBJECT_CONTEXT_FIXTURE_AUTH_EXPIRED');
|
||||
return state;
|
||||
}
|
||||
|
||||
function mutate(state, kind) {
|
||||
const metadata = parseManagedSubjectMetadataV1(state.bytes);
|
||||
if (kind === 'engine-observation-drift') return canonicalManagedSubjectMetadataBytesV1({
|
||||
...metadata, engine: { ...metadata.engine, sha256: '6'.repeat(64) },
|
||||
});
|
||||
if (kind === 'adapter-observation-drift') return canonicalManagedSubjectMetadataBytesV1({
|
||||
...metadata, adapter: { ...metadata.adapter, sha256: '7'.repeat(64) },
|
||||
});
|
||||
if (kind === 'stale-subject-observation') return canonicalManagedSubjectMetadataBytesV1({
|
||||
...metadata, subject: { ...metadata.subject, productCommit: '8'.repeat(40) },
|
||||
});
|
||||
if (kind === 'dirty-subject-claim') return Buffer.concat([state.bytes, frame('S-subject-state', 'dirty')]);
|
||||
if (kind === 'unknown-field') return Buffer.concat([state.bytes, frame('unexpected-field', 'value')]);
|
||||
if (kind === 'mixed-field') return Buffer.concat([state.bytes, frame('S-snapshot-policy-digest', '9'.repeat(64))]);
|
||||
if (kind === 'head-relabel') return Buffer.concat([state.bytes, frame('repository-head', 'a'.repeat(40))]);
|
||||
return canonicalManagedSubjectMetadataBytesV1(metadata);
|
||||
}
|
||||
|
||||
/** Same E/S/A bytes as the data-only metadata module; the digest never implies a loaded or native engine. */
|
||||
export function canonicalCheckSubjectEsaBytesV1(value) {
|
||||
return canonicalManagedSubjectMetadataBytesV1(value);
|
||||
}
|
||||
|
||||
export function checkSubjectEsaDigestV1(value) {
|
||||
const bytes = Buffer.isBuffer(value) || value instanceof Uint8Array
|
||||
? Buffer.from(value)
|
||||
: canonicalCheckSubjectEsaBytesV1(value);
|
||||
parseManagedSubjectMetadataV1(bytes);
|
||||
return sha256(bytes);
|
||||
}
|
||||
|
||||
/** Issues an opaque, fixture-only authority. Callers may supply captured bytes, never roots, readers, or verifiers. */
|
||||
export function createCheckSubjectFixtureHarnessV1(input = {}) {
|
||||
exactObject(input, new Set(['metadataBytes']), 'Fixture harness input');
|
||||
const candidateBytes = input.metadataBytes === undefined
|
||||
? canonicalManagedSubjectMetadataBytesV1(fixtureObservations())
|
||||
: input.metadataBytes;
|
||||
parseManagedSubjectMetadataV1(candidateBytes);
|
||||
const bytes = Buffer.from(candidateBytes);
|
||||
const harness = Object.freeze({
|
||||
schema: 'torch.dev/check-subject-fixture-authority/v1alpha1', fixtureId: `fixture-${randomUUID()}`,
|
||||
});
|
||||
harnesses.set(harness, { bytes, digest: sha256(bytes), used: false, closed: false });
|
||||
return harness;
|
||||
}
|
||||
|
||||
/** Enumerated test-only mutation hook; it cannot target registered metadata or expose a handle. */
|
||||
export function applyCheckSubjectFixtureMutationV1(input = {}) {
|
||||
exactObject(input, new Set(['harness', 'kind']), 'Fixture mutation input');
|
||||
const state = assertHarness(input.harness);
|
||||
if (state.used || !MUTATIONS.has(input.kind)) {
|
||||
fail('Fixture mutation is unsupported', 'CHECK_SUBJECT_CONTEXT_INPUT_INVALID', { kind: input.kind });
|
||||
}
|
||||
state.bytes = mutate(state, input.kind);
|
||||
return Object.freeze({ applied: input.kind });
|
||||
}
|
||||
|
||||
/** Admits only an issued single-use fixture and always marks its result untrusted and nonpromotable. */
|
||||
export function admitFixtureCheckSubjectContextV1(input = {}) {
|
||||
exactObject(input, new Set(['harness']), 'Fixture admission input');
|
||||
const state = assertHarness(input.harness);
|
||||
if (state.used) fail('Fixture authority is single-use', 'CHECK_SUBJECT_CONTEXT_FIXTURE_AUTH_REUSED');
|
||||
const metadata = parseManagedSubjectMetadataV1(state.bytes);
|
||||
if (sha256(state.bytes) !== state.digest) {
|
||||
fail('Fixture observations drifted after issue', 'CHECK_SUBJECT_CONTEXT_FIXTURE_DRIFT');
|
||||
}
|
||||
state.used = true;
|
||||
const context = Object.freeze({
|
||||
schema: 'torch.dev/check-subject-context/v1alpha1',
|
||||
classification: 'fixture-untrusted',
|
||||
promotion: 'nonpromotable',
|
||||
nativeEligible: false,
|
||||
receiptEligible: false,
|
||||
esaDigest: state.digest,
|
||||
metadata,
|
||||
});
|
||||
contexts.set(context, state);
|
||||
return context;
|
||||
}
|
||||
|
||||
export function inspectFixtureCheckSubjectContextV1(input = {}) {
|
||||
exactObject(input, new Set(['context']), 'Fixture inspection input');
|
||||
const state = assertContext(input.context);
|
||||
return Object.freeze({
|
||||
schema: input.context.schema,
|
||||
classification: 'fixture-untrusted',
|
||||
promotion: 'nonpromotable',
|
||||
nativeEligible: false,
|
||||
receiptEligible: false,
|
||||
esaDigest: state.digest,
|
||||
metadata: input.context.metadata,
|
||||
});
|
||||
}
|
||||
|
||||
export function closeCheckSubjectFixtureHarnessV1(input = {}) {
|
||||
exactObject(input, new Set(['harness']), 'Fixture close input');
|
||||
const state = assertHarness(input.harness);
|
||||
state.closed = true;
|
||||
return Object.freeze({ closed: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* B1 deliberately has no reachable registered parent issuer. It may parse untrusted bytes for a
|
||||
* compatibility refusal, but it never opens a control plane, reads a database, or returns authority.
|
||||
*/
|
||||
export function admitRegisteredCheckSubjectContextV1(input = {}) {
|
||||
exactObject(input, new Set(['metadataBytes', 'requiredStorageSchemaVersion', 'currentStorageSchemaVersion']), 'Registered admission input');
|
||||
if (input.metadataBytes !== undefined) parseManagedSubjectMetadataV1(input.metadataBytes);
|
||||
const required = input.requiredStorageSchemaVersion;
|
||||
const current = input.currentStorageSchemaVersion;
|
||||
if (required !== undefined || current !== undefined) {
|
||||
if (!Number.isSafeInteger(required) || required < 1 || !Number.isSafeInteger(current) || current < 1) {
|
||||
fail('Registered schema observations are invalid', 'CHECK_SUBJECT_CONTEXT_INPUT_INVALID');
|
||||
}
|
||||
if (required !== current) {
|
||||
fail('Registered schema is incompatible with the required schema', 'CHECK_SUBJECT_CONTEXT_SCHEMA_INCOMPATIBLE', { required, current });
|
||||
}
|
||||
}
|
||||
fail('No registered parent composition is available in B1', 'CHECK_SUBJECT_CONTEXT_MISSING_COMPOSITION');
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
import { TorchError } from './errors.mjs';
|
||||
|
||||
export const MANAGED_SUBJECT_METADATA_PROTOCOL_VERSION = 1;
|
||||
export const MANAGED_SUBJECT_METADATA_MAX_FRAME_BYTES = 1024 * 1024;
|
||||
|
||||
const SCHEMA = 'torch.dev/managed-subject-metadata/v1alpha1';
|
||||
const SHA256 = /^[0-9a-f]{64}$/;
|
||||
const COMMIT = /^[0-9a-f]{40}$/;
|
||||
const IDENTIFIER = /^[a-z0-9][a-z0-9._/-]{0,127}$/;
|
||||
const FRAME_LABELS = Object.freeze([
|
||||
'schema', 'protocol-version',
|
||||
'E-module-id', 'E-interface-version', 'E-byte-length', 'E-sha256',
|
||||
'S-project-id', 'S-product-commit', 'S-clean-tree-digest', 'S-storage-schema-version', 'S-storage-schema-digest',
|
||||
'A-module-id', 'A-interface-version', 'A-byte-length', 'A-sha256',
|
||||
'A-control-plane-schema-version', 'A-compatible-storage-schema-version', 'A-compatible-storage-schema-digest',
|
||||
]);
|
||||
|
||||
function fail(message, code, details) {
|
||||
throw new TorchError(message, { code, details });
|
||||
}
|
||||
|
||||
function exactObject(value, allowed, label) {
|
||||
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
||||
fail(`${label} must be an object`, 'MANAGED_SUBJECT_METADATA_INVALID');
|
||||
}
|
||||
for (const key of Object.keys(value)) {
|
||||
if (!allowed.has(key)) fail(`${label} contains an unsupported field`, 'MANAGED_SUBJECT_METADATA_INVALID', { field: key });
|
||||
}
|
||||
}
|
||||
|
||||
function boundedString(value, field, pattern = null) {
|
||||
if (typeof value !== 'string' || !value || Buffer.byteLength(value, 'utf8') > 256 || (pattern && !pattern.test(value))) {
|
||||
fail(`${field} is invalid`, 'MANAGED_SUBJECT_METADATA_INVALID', { field });
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function positiveInteger(value, field) {
|
||||
if (!Number.isSafeInteger(value) || value < 1) {
|
||||
fail(`${field} must be a positive safe integer`, 'MANAGED_SUBJECT_METADATA_INVALID', { field });
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function byteLength(value, field) {
|
||||
if (!Number.isSafeInteger(value) || value < 0) {
|
||||
fail(`${field} must be a non-negative safe integer`, 'MANAGED_SUBJECT_METADATA_INVALID', { field });
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function freezeMetadata(metadata) {
|
||||
return Object.freeze({
|
||||
schema: metadata.schema,
|
||||
protocolVersion: metadata.protocolVersion,
|
||||
engine: Object.freeze({ ...metadata.engine }),
|
||||
subject: Object.freeze({ ...metadata.subject }),
|
||||
adapter: Object.freeze({ ...metadata.adapter }),
|
||||
});
|
||||
}
|
||||
|
||||
function frame(label, value) {
|
||||
const bytes = Buffer.from(value, 'utf8');
|
||||
return Buffer.concat([Buffer.from(`${label}:${bytes.length}\n`, 'ascii'), bytes, Buffer.from('\n', 'ascii')]);
|
||||
}
|
||||
|
||||
function decodeUtf8(bytes, field) {
|
||||
try {
|
||||
return new TextDecoder('utf-8', { fatal: true }).decode(bytes);
|
||||
} catch {
|
||||
fail(`${field} is not valid UTF-8`, 'MANAGED_SUBJECT_METADATA_INVALID', { field });
|
||||
}
|
||||
}
|
||||
|
||||
function capturedBytes(value) {
|
||||
if (!(Buffer.isBuffer(value) || value instanceof Uint8Array)) {
|
||||
fail('Metadata must be captured bytes', 'MANAGED_SUBJECT_METADATA_INVALID');
|
||||
}
|
||||
const bytes = Buffer.from(value);
|
||||
if (!bytes.length || bytes.length > MANAGED_SUBJECT_METADATA_MAX_FRAME_BYTES) {
|
||||
fail('Metadata frame exceeds the v1 bound', 'MANAGED_SUBJECT_METADATA_FRAME_TOO_LARGE');
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function parseFrames(bytes) {
|
||||
const fields = new Map();
|
||||
let offset = 0;
|
||||
while (offset < bytes.length) {
|
||||
const headerEnd = bytes.indexOf(0x0a, offset);
|
||||
if (headerEnd === -1) fail('Metadata frame header is incomplete', 'MANAGED_SUBJECT_METADATA_INVALID');
|
||||
const header = bytes.subarray(offset, headerEnd).toString('ascii');
|
||||
const match = /^([A-Za-z0-9-]+):([0-9]+)$/.exec(header);
|
||||
if (!match || (match[2].length > 1 && match[2].startsWith('0'))) {
|
||||
fail('Metadata frame header is malformed', 'MANAGED_SUBJECT_METADATA_INVALID');
|
||||
}
|
||||
const [, label, lengthText] = match;
|
||||
const length = Number(lengthText);
|
||||
if (!Number.isSafeInteger(length) || length > MANAGED_SUBJECT_METADATA_MAX_FRAME_BYTES) {
|
||||
fail('Metadata frame length is invalid', 'MANAGED_SUBJECT_METADATA_INVALID');
|
||||
}
|
||||
const valueStart = headerEnd + 1;
|
||||
const valueEnd = valueStart + length;
|
||||
if (valueEnd >= bytes.length || bytes[valueEnd] !== 0x0a || fields.has(label)) {
|
||||
fail('Metadata frame body is malformed', 'MANAGED_SUBJECT_METADATA_INVALID');
|
||||
}
|
||||
fields.set(label, decodeUtf8(bytes.subarray(valueStart, valueEnd), label));
|
||||
offset = valueEnd + 1;
|
||||
}
|
||||
if (fields.size !== FRAME_LABELS.length || FRAME_LABELS.some((label) => !fields.has(label))) {
|
||||
fail('Metadata frame fields are unsupported or incomplete', 'MANAGED_SUBJECT_METADATA_INVALID');
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
/** Validates only captured E/S/A observations. It intentionally has no authority or filesystem inputs. */
|
||||
export function validateManagedSubjectMetadataV1(value) {
|
||||
exactObject(value, new Set(['schema', 'protocolVersion', 'engine', 'subject', 'adapter']), 'Metadata');
|
||||
if (value.schema !== SCHEMA || value.protocolVersion !== MANAGED_SUBJECT_METADATA_PROTOCOL_VERSION) {
|
||||
fail('Metadata protocol is unsupported', 'MANAGED_SUBJECT_METADATA_INVALID');
|
||||
}
|
||||
exactObject(value.engine, new Set(['moduleId', 'interfaceVersion', 'byteLength', 'sha256']), 'Engine observation');
|
||||
exactObject(value.subject, new Set(['projectId', 'productCommit', 'cleanTreeDigest', 'storageSchemaVersion', 'storageSchemaDigest']), 'Subject observation');
|
||||
exactObject(value.adapter, new Set([
|
||||
'moduleId', 'interfaceVersion', 'byteLength', 'sha256', 'controlPlaneSchemaVersion',
|
||||
'compatibleStorageSchemaVersion', 'compatibleStorageSchemaDigest',
|
||||
]), 'Adapter observation');
|
||||
const metadata = {
|
||||
schema: SCHEMA,
|
||||
protocolVersion: MANAGED_SUBJECT_METADATA_PROTOCOL_VERSION,
|
||||
engine: {
|
||||
moduleId: boundedString(value.engine.moduleId, 'engine.moduleId', IDENTIFIER),
|
||||
interfaceVersion: positiveInteger(value.engine.interfaceVersion, 'engine.interfaceVersion'),
|
||||
byteLength: byteLength(value.engine.byteLength, 'engine.byteLength'),
|
||||
sha256: boundedString(value.engine.sha256, 'engine.sha256', SHA256),
|
||||
},
|
||||
subject: {
|
||||
projectId: boundedString(value.subject.projectId, 'subject.projectId', IDENTIFIER),
|
||||
productCommit: boundedString(value.subject.productCommit, 'subject.productCommit', COMMIT),
|
||||
cleanTreeDigest: boundedString(value.subject.cleanTreeDigest, 'subject.cleanTreeDigest', SHA256),
|
||||
storageSchemaVersion: positiveInteger(value.subject.storageSchemaVersion, 'subject.storageSchemaVersion'),
|
||||
storageSchemaDigest: boundedString(value.subject.storageSchemaDigest, 'subject.storageSchemaDigest', SHA256),
|
||||
},
|
||||
adapter: {
|
||||
moduleId: boundedString(value.adapter.moduleId, 'adapter.moduleId', IDENTIFIER),
|
||||
interfaceVersion: positiveInteger(value.adapter.interfaceVersion, 'adapter.interfaceVersion'),
|
||||
byteLength: byteLength(value.adapter.byteLength, 'adapter.byteLength'),
|
||||
sha256: boundedString(value.adapter.sha256, 'adapter.sha256', SHA256),
|
||||
controlPlaneSchemaVersion: positiveInteger(value.adapter.controlPlaneSchemaVersion, 'adapter.controlPlaneSchemaVersion'),
|
||||
compatibleStorageSchemaVersion: positiveInteger(value.adapter.compatibleStorageSchemaVersion, 'adapter.compatibleStorageSchemaVersion'),
|
||||
compatibleStorageSchemaDigest: boundedString(value.adapter.compatibleStorageSchemaDigest, 'adapter.compatibleStorageSchemaDigest', SHA256),
|
||||
},
|
||||
};
|
||||
return freezeMetadata(metadata);
|
||||
}
|
||||
|
||||
/** Canonical bounded UTF-8/LF bytes for independent engine, subject, and adapter observations. */
|
||||
export function canonicalManagedSubjectMetadataBytesV1(value) {
|
||||
const metadata = validateManagedSubjectMetadataV1(value);
|
||||
const fields = [
|
||||
['schema', metadata.schema], ['protocol-version', String(metadata.protocolVersion)],
|
||||
['E-module-id', metadata.engine.moduleId], ['E-interface-version', String(metadata.engine.interfaceVersion)],
|
||||
['E-byte-length', String(metadata.engine.byteLength)], ['E-sha256', metadata.engine.sha256],
|
||||
['S-project-id', metadata.subject.projectId], ['S-product-commit', metadata.subject.productCommit],
|
||||
['S-clean-tree-digest', metadata.subject.cleanTreeDigest], ['S-storage-schema-version', String(metadata.subject.storageSchemaVersion)],
|
||||
['S-storage-schema-digest', metadata.subject.storageSchemaDigest],
|
||||
['A-module-id', metadata.adapter.moduleId], ['A-interface-version', String(metadata.adapter.interfaceVersion)],
|
||||
['A-byte-length', String(metadata.adapter.byteLength)], ['A-sha256', metadata.adapter.sha256],
|
||||
['A-control-plane-schema-version', String(metadata.adapter.controlPlaneSchemaVersion)],
|
||||
['A-compatible-storage-schema-version', String(metadata.adapter.compatibleStorageSchemaVersion)],
|
||||
['A-compatible-storage-schema-digest', metadata.adapter.compatibleStorageSchemaDigest],
|
||||
];
|
||||
const bytes = Buffer.concat(fields.map(([label, field]) => frame(label, field)));
|
||||
if (bytes.length > MANAGED_SUBJECT_METADATA_MAX_FRAME_BYTES) {
|
||||
fail('Metadata frame exceeds the v1 bound', 'MANAGED_SUBJECT_METADATA_FRAME_TOO_LARGE');
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/** Parses captured bytes only; accepted v1 bytes describe untrusted observations, never native authority. */
|
||||
export function parseManagedSubjectMetadataV1(value) {
|
||||
const bytes = capturedBytes(value);
|
||||
const fields = parseFrames(bytes);
|
||||
const metadata = validateManagedSubjectMetadataV1({
|
||||
schema: fields.get('schema'),
|
||||
protocolVersion: Number(fields.get('protocol-version')),
|
||||
engine: {
|
||||
moduleId: fields.get('E-module-id'), interfaceVersion: Number(fields.get('E-interface-version')),
|
||||
byteLength: Number(fields.get('E-byte-length')), sha256: fields.get('E-sha256'),
|
||||
},
|
||||
subject: {
|
||||
projectId: fields.get('S-project-id'), productCommit: fields.get('S-product-commit'),
|
||||
cleanTreeDigest: fields.get('S-clean-tree-digest'), storageSchemaVersion: Number(fields.get('S-storage-schema-version')),
|
||||
storageSchemaDigest: fields.get('S-storage-schema-digest'),
|
||||
},
|
||||
adapter: {
|
||||
moduleId: fields.get('A-module-id'), interfaceVersion: Number(fields.get('A-interface-version')),
|
||||
byteLength: Number(fields.get('A-byte-length')), sha256: fields.get('A-sha256'),
|
||||
controlPlaneSchemaVersion: Number(fields.get('A-control-plane-schema-version')),
|
||||
compatibleStorageSchemaVersion: Number(fields.get('A-compatible-storage-schema-version')),
|
||||
compatibleStorageSchemaDigest: fields.get('A-compatible-storage-schema-digest'),
|
||||
},
|
||||
});
|
||||
if (!Buffer.from(canonicalManagedSubjectMetadataBytesV1(metadata)).equals(bytes)) {
|
||||
fail('Metadata bytes are not canonical v1 observations', 'MANAGED_SUBJECT_METADATA_INVALID');
|
||||
}
|
||||
return metadata;
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { createHash } from 'node:crypto';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import test from 'node:test';
|
||||
import {
|
||||
MANAGED_SUBJECT_METADATA_MAX_FRAME_BYTES,
|
||||
MANAGED_SUBJECT_METADATA_PROTOCOL_VERSION,
|
||||
canonicalManagedSubjectMetadataBytesV1,
|
||||
parseManagedSubjectMetadataV1,
|
||||
validateManagedSubjectMetadataV1,
|
||||
} from '../../src/kernel/managed-subject-metadata.mjs';
|
||||
import {
|
||||
CHECK_SUBJECT_CONTEXT_PROTOCOL_VERSION,
|
||||
admitFixtureCheckSubjectContextV1,
|
||||
admitRegisteredCheckSubjectContextV1,
|
||||
applyCheckSubjectFixtureMutationV1,
|
||||
canonicalCheckSubjectEsaBytesV1,
|
||||
checkSubjectEsaDigestV1,
|
||||
closeCheckSubjectFixtureHarnessV1,
|
||||
createCheckSubjectFixtureHarnessV1,
|
||||
inspectFixtureCheckSubjectContextV1,
|
||||
} from '../../src/kernel/check-subject-context.mjs';
|
||||
|
||||
const observations = Object.freeze({
|
||||
schema: 'torch.dev/managed-subject-metadata/v1alpha1',
|
||||
protocolVersion: 1,
|
||||
engine: Object.freeze({ moduleId: 'candidate-engine', interfaceVersion: 1, byteLength: 4096, sha256: '1'.repeat(64) }),
|
||||
subject: Object.freeze({
|
||||
projectId: 'fixture-project', productCommit: '2'.repeat(40), cleanTreeDigest: '3'.repeat(64),
|
||||
storageSchemaVersion: 2, storageSchemaDigest: '4'.repeat(64),
|
||||
}),
|
||||
adapter: Object.freeze({
|
||||
moduleId: 'fixture-adapter', interfaceVersion: 1, byteLength: 2048, sha256: '5'.repeat(64),
|
||||
controlPlaneSchemaVersion: 2, compatibleStorageSchemaVersion: 2, compatibleStorageSchemaDigest: '4'.repeat(64),
|
||||
}),
|
||||
});
|
||||
|
||||
function frame(label, value) {
|
||||
const bytes = Buffer.from(value, 'utf8');
|
||||
return Buffer.from(`${label}:${bytes.length}\n${value}\n`, 'utf8');
|
||||
}
|
||||
|
||||
function independentlyFramedBytes(value = observations) {
|
||||
return Buffer.concat([
|
||||
frame('schema', value.schema), frame('protocol-version', String(value.protocolVersion)),
|
||||
frame('E-module-id', value.engine.moduleId), frame('E-interface-version', String(value.engine.interfaceVersion)),
|
||||
frame('E-byte-length', String(value.engine.byteLength)), frame('E-sha256', value.engine.sha256),
|
||||
frame('S-project-id', value.subject.projectId), frame('S-product-commit', value.subject.productCommit),
|
||||
frame('S-clean-tree-digest', value.subject.cleanTreeDigest), frame('S-storage-schema-version', String(value.subject.storageSchemaVersion)),
|
||||
frame('S-storage-schema-digest', value.subject.storageSchemaDigest),
|
||||
frame('A-module-id', value.adapter.moduleId), frame('A-interface-version', String(value.adapter.interfaceVersion)),
|
||||
frame('A-byte-length', String(value.adapter.byteLength)), frame('A-sha256', value.adapter.sha256),
|
||||
frame('A-control-plane-schema-version', String(value.adapter.controlPlaneSchemaVersion)),
|
||||
frame('A-compatible-storage-schema-version', String(value.adapter.compatibleStorageSchemaVersion)),
|
||||
frame('A-compatible-storage-schema-digest', value.adapter.compatibleStorageSchemaDigest),
|
||||
]);
|
||||
}
|
||||
|
||||
function expectCode(callback, code) {
|
||||
assert.throws(callback, (error) => error.code === code);
|
||||
}
|
||||
|
||||
test('SCN-check-subject-context-canonical-E-S-A: independently framed captured observations bind separate engine, subject, and adapter bytes', async () => {
|
||||
const metadata = await import('../../src/kernel/managed-subject-metadata.mjs');
|
||||
const context = await import('../../src/kernel/check-subject-context.mjs');
|
||||
const bytes = independentlyFramedBytes();
|
||||
assert.equal(MANAGED_SUBJECT_METADATA_PROTOCOL_VERSION, 1);
|
||||
assert.equal(CHECK_SUBJECT_CONTEXT_PROTOCOL_VERSION, 1);
|
||||
assert.deepEqual(Object.keys(metadata), [
|
||||
'MANAGED_SUBJECT_METADATA_MAX_FRAME_BYTES', 'MANAGED_SUBJECT_METADATA_PROTOCOL_VERSION',
|
||||
'canonicalManagedSubjectMetadataBytesV1', 'parseManagedSubjectMetadataV1', 'validateManagedSubjectMetadataV1',
|
||||
]);
|
||||
assert.deepEqual(Object.keys(context), [
|
||||
'CHECK_SUBJECT_CONTEXT_PROTOCOL_VERSION', 'admitFixtureCheckSubjectContextV1', 'admitRegisteredCheckSubjectContextV1',
|
||||
'applyCheckSubjectFixtureMutationV1', 'canonicalCheckSubjectEsaBytesV1', 'checkSubjectEsaDigestV1',
|
||||
'closeCheckSubjectFixtureHarnessV1', 'createCheckSubjectFixtureHarnessV1', 'inspectFixtureCheckSubjectContextV1',
|
||||
]);
|
||||
assert.deepEqual(canonicalManagedSubjectMetadataBytesV1(observations), bytes);
|
||||
assert.deepEqual(canonicalCheckSubjectEsaBytesV1(observations), bytes);
|
||||
assert.equal(checkSubjectEsaDigestV1(bytes), createHash('sha256').update(bytes).digest('hex'));
|
||||
assert.deepEqual(parseManagedSubjectMetadataV1(bytes), validateManagedSubjectMetadataV1(observations));
|
||||
});
|
||||
|
||||
test('SCN-check-subject-context-v1-refusal: parent, native, loaded-engine, V2, selectors, and oversized bytes cannot reinterpret fixture observations', () => {
|
||||
const bytes = independentlyFramedBytes();
|
||||
expectCode(() => canonicalManagedSubjectMetadataBytesV1({ ...observations, parentBinding: 'forged' }), 'MANAGED_SUBJECT_METADATA_INVALID');
|
||||
expectCode(() => canonicalManagedSubjectMetadataBytesV1({ ...observations, engine: { ...observations.engine, loadedEngine: true } }), 'MANAGED_SUBJECT_METADATA_INVALID');
|
||||
expectCode(() => parseManagedSubjectMetadataV1(Buffer.concat([bytes, frame('S-snapshot-policy-digest', '9'.repeat(64))])), 'MANAGED_SUBJECT_METADATA_INVALID');
|
||||
expectCode(() => parseManagedSubjectMetadataV1(Buffer.concat([bytes, frame('native-eligible', 'true')])), 'MANAGED_SUBJECT_METADATA_INVALID');
|
||||
expectCode(() => parseManagedSubjectMetadataV1(Buffer.alloc(MANAGED_SUBJECT_METADATA_MAX_FRAME_BYTES + 1)), 'MANAGED_SUBJECT_METADATA_FRAME_TOO_LARGE');
|
||||
|
||||
let bytesRead = false;
|
||||
const selectorBeforeParse = { root: '/tmp/not-authority', get metadataBytes() { bytesRead = true; return bytes; } };
|
||||
expectCode(() => createCheckSubjectFixtureHarnessV1(selectorBeforeParse), 'CHECK_SUBJECT_CONTEXT_INPUT_INVALID');
|
||||
assert.equal(bytesRead, false, 'public selectors must fail before metadata parsing');
|
||||
for (const selector of ['root', 'database', 'ddl', 'manifest', 'metadataReader', 'engineVerifier', 'adapterSelector', 'path']) {
|
||||
let selectorBytesRead = false;
|
||||
const input = { [selector]: 'forged', get metadataBytes() { selectorBytesRead = true; return bytes; } };
|
||||
expectCode(() => admitRegisteredCheckSubjectContextV1(input), 'CHECK_SUBJECT_CONTEXT_INPUT_INVALID');
|
||||
assert.equal(selectorBytesRead, false, `${selector} must fail before parsing`);
|
||||
}
|
||||
});
|
||||
|
||||
test('SCN-check-subject-context-fixture-authority: issued-only, single-use fixture admission is clone-, expiry-, and promotion-resistant', () => {
|
||||
const harness = createCheckSubjectFixtureHarnessV1({ metadataBytes: independentlyFramedBytes() });
|
||||
const copiedHarness = Object.freeze({ ...harness });
|
||||
expectCode(() => admitFixtureCheckSubjectContextV1({ harness: copiedHarness }), 'CHECK_SUBJECT_CONTEXT_FIXTURE_AUTH_REQUIRED');
|
||||
const context = admitFixtureCheckSubjectContextV1({ harness });
|
||||
assert.deepEqual({
|
||||
classification: context.classification, promotion: context.promotion,
|
||||
nativeEligible: context.nativeEligible, receiptEligible: context.receiptEligible,
|
||||
}, { classification: 'fixture-untrusted', promotion: 'nonpromotable', nativeEligible: false, receiptEligible: false });
|
||||
assert.equal(Object.hasOwn(context, 'receipt'), false);
|
||||
expectCode(() => admitFixtureCheckSubjectContextV1({ harness }), 'CHECK_SUBJECT_CONTEXT_FIXTURE_AUTH_REUSED');
|
||||
expectCode(() => inspectFixtureCheckSubjectContextV1({ context: Object.freeze({ ...context }) }), 'CHECK_SUBJECT_CONTEXT_FIXTURE_AUTH_REQUIRED');
|
||||
expectCode(() => inspectFixtureCheckSubjectContextV1({ context: { schema: context.schema } }), 'CHECK_SUBJECT_CONTEXT_FIXTURE_AUTH_REQUIRED');
|
||||
assert.deepEqual(inspectFixtureCheckSubjectContextV1({ context }), context);
|
||||
closeCheckSubjectFixtureHarnessV1({ harness });
|
||||
expectCode(() => inspectFixtureCheckSubjectContextV1({ context }), 'CHECK_SUBJECT_CONTEXT_FIXTURE_AUTH_EXPIRED');
|
||||
});
|
||||
|
||||
test('SCN-check-subject-context-mutation-resistance: independently observed E/S/A drift and noncanonical claims fail closed', () => {
|
||||
for (const [kind, code] of [
|
||||
['engine-observation-drift', 'CHECK_SUBJECT_CONTEXT_FIXTURE_DRIFT'],
|
||||
['adapter-observation-drift', 'CHECK_SUBJECT_CONTEXT_FIXTURE_DRIFT'],
|
||||
['stale-subject-observation', 'CHECK_SUBJECT_CONTEXT_FIXTURE_DRIFT'],
|
||||
['dirty-subject-claim', 'MANAGED_SUBJECT_METADATA_INVALID'],
|
||||
['unknown-field', 'MANAGED_SUBJECT_METADATA_INVALID'],
|
||||
['mixed-field', 'MANAGED_SUBJECT_METADATA_INVALID'],
|
||||
['head-relabel', 'MANAGED_SUBJECT_METADATA_INVALID'],
|
||||
]) {
|
||||
const harness = createCheckSubjectFixtureHarnessV1({ metadataBytes: independentlyFramedBytes() });
|
||||
applyCheckSubjectFixtureMutationV1({ harness, kind });
|
||||
expectCode(() => admitFixtureCheckSubjectContextV1({ harness }), code);
|
||||
closeCheckSubjectFixtureHarnessV1({ harness });
|
||||
}
|
||||
});
|
||||
|
||||
test('SCN-check-subject-context-schema-and-native-refusal: schema2 is readable legacy evidence, current2-required3 and all registered v1 admission refuse without state access', () => {
|
||||
const bytes = independentlyFramedBytes();
|
||||
assert.equal(parseManagedSubjectMetadataV1(bytes).subject.storageSchemaVersion, 2);
|
||||
expectCode(() => admitRegisteredCheckSubjectContextV1({
|
||||
metadataBytes: bytes, requiredStorageSchemaVersion: 3, currentStorageSchemaVersion: 2,
|
||||
}), 'CHECK_SUBJECT_CONTEXT_SCHEMA_INCOMPATIBLE');
|
||||
expectCode(() => admitRegisteredCheckSubjectContextV1({
|
||||
metadataBytes: bytes, requiredStorageSchemaVersion: 2, currentStorageSchemaVersion: 2,
|
||||
}), 'CHECK_SUBJECT_CONTEXT_MISSING_COMPOSITION');
|
||||
expectCode(() => admitRegisteredCheckSubjectContextV1(), 'CHECK_SUBJECT_CONTEXT_MISSING_COMPOSITION');
|
||||
const source = `${readFileSync(new URL('../../src/kernel/managed-subject-metadata.mjs', import.meta.url), 'utf8')}\n${readFileSync(new URL('../../src/kernel/check-subject-context.mjs', import.meta.url), 'utf8')}`;
|
||||
for (const forbidden of ['ControlPlane', 'openControlPlane', 'DatabaseSync', "node:sqlite", '.prepare(']) {
|
||||
assert.equal(source.includes(forbidden), false, `B1 data-only modules must not invoke ${forbidden}`);
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user