Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ Read [Architecture](docs/architecture.md), [Contracts and conformance](docs/cont
- An unsigned Execution Passport proves deterministic integrity and cross-artifact binding only. Authenticity requires an externally verified DSSE envelope or equivalent trusted channel, and consumers must make that requirement explicit so removing a signature cannot silently downgrade policy.
- The OASF subject digest proves which opaque record was bound; it does not prove that the record is semantically valid OASF. Validate it before passport creation with the specification owner’s tooling.
- Execution-placement evidence enters the predicate only as a strict, run-bound, observation-only descriptor with a normalized observation time and no payload or `content` field. A StageFabric descriptor hashes the exact canonical JSON file bytes, including its trailing LF. Descriptor metadata must come from a trusted producer and be redacted or pseudonymized when sensitive; its optional stable URI may be omitted. Full provider result objects are outside the Passport contract.
- The StageFabric adapter follows its finalized `0.7.0-alpha.1` successful-run contract: trace events are either completed placements or pre-output retries with status `429`, `502`, `503`, or `504`. Terminal failures, arbitrary HTTP codes, missing retry codes, and codes attached to completed events fail closed.
- A safe fingerprint binds the declared canonical intent. It does not prove that an upstream intent normalizer chose the correct meaning.
- Adapter documents are integration contracts, not bundled protocol SDKs or policy engines.
- The current release is an alpha contract surface. Version consumers explicitly before production adoption.
Expand Down
2 changes: 1 addition & 1 deletion adapters/stagefabric.mapping.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ direction: inbound
contractBindings:
- strataContract: ExecutionEvidenceBinding
protocolObject: ExecutionPlacementEvidence
notes: The executable adapter validates strict source schema, semantic trace, timestamp grammar, seal, and exact canonical-JSON-plus-LF writer bytes; converts the prefixed run digest; normalizes observedAt; fixes authority to observation-only; and hashes the retrievable file bytes.
notes: The executable adapter validates strict successful-run source schema, admits only completed events or pre-output retries with status 429/502/503/504, verifies semantic trace, timestamp grammar, seal, and exact canonical-JSON-plus-LF writer bytes; converts the prefixed run digest; normalizes observedAt; fixes authority to observation-only; and hashes the retrievable file bytes.
- strataContract: ExecutionPassport
protocolObject: predicate executionEvidence entry
notes: Passport creation rejects a source from another run. No payload or content field is admitted, and placement never grants executable authority.
Expand Down
2 changes: 1 addition & 1 deletion docs/adr/0005-run-bound-execution-evidence.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Execution Passport v2 requires every `ExecutionEvidenceBinding` to carry `runIdD

Provider integrations are explicit reduction adapters. They validate the external artifact schema and producer seal, bind the complete artifact by digest, and emit only a strict descriptor.

The StageFabric adapter binds the exact canonical JSON file bytes written by StageFabric, including its trailing LF, rather than hashing a reparsed object. Its CLI path rejects alternative encodings so a URI can be verified byte-for-byte against the descriptor.
The StageFabric adapter binds the exact canonical JSON file bytes written by StageFabric, including its trailing LF, rather than hashing a reparsed object. Its CLI path rejects alternative encodings so a URI can be verified byte-for-byte against the descriptor. The finalized `0.7.0-alpha.1` successful-run contract admits only completed events and pre-output retries with status `429`, `502`, `503`, or `504`; terminal failures require a distinct producer artifact and cannot be relabeled into this binding.

The evidence can explain where execution was observed. It cannot issue a grant, widen a grant, authorize a capability, or override an authority check. Provider payloads and result objects remain outside the Passport.

Expand Down
2 changes: 1 addition & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ Passport creation is a deterministic packaging step after conformance evaluation
2. the canonical digest of the complete `ConformanceReport`, including its own `digest` field;
3. the canonical digest of one opaque, externally validated OASF record.

Optional execution-placement evidence is reduced to a `ResourceDescriptor` with no payload or `content` field. AgenticStrata admits only the descriptor, producer identity, fixed role, canonical run-identifier digest, normalized observation time, `observation-only` authority, and `content-free` disclosure marker. A StageFabric adapter validates the source artifact, semantic trace, timestamp grammar, producer seal, and exact canonical-JSON-plus-LF writer bytes before reduction. Descriptor metadata must be trusted and redacted or pseudonymized when sensitive, and its URI may be omitted. A placement observation never grants authority; a descriptor from another run or after the report is rejected.
Optional execution-placement evidence is reduced to a `ResourceDescriptor` with no payload or `content` field. AgenticStrata admits only the descriptor, producer identity, fixed role, canonical run-identifier digest, normalized observation time, `observation-only` authority, and `content-free` disclosure marker. A StageFabric adapter validates the source artifact, its successful-run-only trace (`completed` or a pre-output retry with `429`, `502`, `503`, or `504`), timestamp grammar, producer seal, and exact canonical-JSON-plus-LF writer bytes before reduction. Descriptor metadata must be trusted and redacted or pseudonymized when sensitive, and its URI may be omitted. A placement observation never grants authority; a descriptor from another run or after the report is rejected.

The core emits an unsigned Statement. A replaceable external adapter may wrap its exact RFC 8785 bytes in DSSE and use Sigstore or another trust system. Signature verification, signer identity, transparency-log policy, and trusted time remain consumer-owned controls.

Expand Down
2 changes: 1 addition & 1 deletion docs/contracts-and-conformance.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ The predicate records `runStatus` and `conformanceStatus` separately. Creation d

OASF input is accepted only as an opaque I-JSON object and canonicalized for its subject digest. AgenticStrata deliberately does not carry an OASF schema and therefore does not claim semantic validity. A caller must validate the record externally and provide the owner-declared media type.

`executionEvidence` accepts only strict bindings with no payload or `content` field. Every binding carries the canonical digest of the observed run identifier, normalized observation time, and fixed `observation-only` authority; a run mismatch or observation later than the report fails Passport creation. The StageFabric reduction adapter verifies the source schema, semantic invariants, producer seal, timestamp grammar, and exact writer encoding, then binds the complete canonical-JSON-plus-LF file bytes. AgenticStrata never imports a full provider result. Descriptor metadata must be trusted and redacted or pseudonymized when sensitive, and the URI may be omitted.
`executionEvidence` accepts only strict bindings with no payload or `content` field. Every binding carries the canonical digest of the observed run identifier, normalized observation time, and fixed `observation-only` authority; a run mismatch or observation later than the report fails Passport creation. The StageFabric reduction adapter verifies the source schema, semantic invariants, producer seal, timestamp grammar, and exact writer encoding, then binds the complete canonical-JSON-plus-LF file bytes. Its successful-run trace is closed to `completed` events and pre-output retries with status `429`, `502`, `503`, or `504`; terminal failures and every other status shape are invalid. AgenticStrata never imports a full provider result. Descriptor metadata must be trusted and redacted or pseudonymized when sensitive, and the URI may be omitted.

The Passport is created after assessment and is not required by a conformance rule. Making it a prerequisite of the report it contains would create a circular dependency.

Expand Down
2 changes: 1 addition & 1 deletion docs/interoperability.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ AgenticStrata owns application-level runtime invariants. It deliberately leaves
| Policy engine | Grant, approval, attenuation query | The external enforcement point remains authoritative. |
| OASF | Opaque agent-record subject descriptor | AgenticStrata binds canonical bytes but delegates semantic validation and media-type ownership. |
| in-toto / DSSE | Execution Passport Statement and optional external envelope | The core owns deterministic binding; signing, identity, transparency, and trusted time stay outside it. |
| StageFabric | Sealed content-free placement artifact reduced to an evidence descriptor | Adapter verifies schema, seal, exact writer bytes, run binding, and observation time; the result is observation-only and cannot expand authority. |
| StageFabric | Sealed content-free placement artifact reduced to an evidence descriptor | Adapter verifies the finalized successful-run trace (`completed` or retry `429`/`502`/`503`/`504`), seal, exact writer bytes, run binding, and observation time; the result is observation-only and cannot expand authority. |
| Other execution-placement provider | Content-free, run-bound evidence descriptor | No payload or `content` field is admitted; producer validation remains an explicit adapter responsibility. |

Adapter YAML files are declarative mappings with an explicit `lossPolicy`. They contain no vendor SDK and can be replaced without changing the core contract registry.
Expand Down
2 changes: 1 addition & 1 deletion docs/spec/attestations/execution-passport/v2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Every `ExecutionEvidenceBinding` contains exactly:

The builder rejects a binding when `runIdDigest` does not match the bound run, when two evidence artifacts share a digest, when `observedAt` is later than the report, or when the descriptor is not strict. An observation can support lineage but cannot grant, widen, or substitute executable authority.

For StageFabric, the resource digest is SHA-256 over the exact UTF-8 bytes written by its safe writer: canonical JSON for the complete evidence object, including the producer seal, followed by one LF byte. The CLI rejects YAML, pretty JSON, missing or extra whitespace, and other reserializations. If a descriptor carries a URI, retrieval must return those exact bytes.
For StageFabric, the resource digest is SHA-256 over the exact UTF-8 bytes written by its safe writer: canonical JSON for the complete evidence object, including the producer seal, followed by one LF byte. The adapter accepts only its successful-run trace variants: `completed`, or `retryable_pre_output_status` with `429`, `502`, `503`, or `504`. The CLI rejects YAML, pretty JSON, missing or extra whitespace, and other reserializations. If a descriptor carries a URI, retrieval must return those exact bytes.

Provider adapters must validate their source contract and seal before creating a binding. They must not copy stage names, targets, prompts, model input or output, credentials, paths, or provider result objects into the binding. Descriptor metadata can still be sensitive and must be redacted or pseudonymized; the URI is optional.

Expand Down
1 change: 1 addition & 0 deletions docs/threat-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Model output, retrieved content, external messages, tool descriptions, and impor
| A Passport is interpreted as proof of success | The predicate carries separate explicit run and conformance statuses and permits failed or incomplete states. | Consumers must still enforce the statuses appropriate to their decision. |
| Raw execution data leaks through placement evidence | The schema and CLI reject payload/content fields, inline or local URI schemes, credentialed HTTPS references, query strings, fragments, and oversized URIs. | Descriptor names, producer identifiers, media types, HTTPS paths, and URNs remain metadata channels; accept them only from trusted producers and redact, pseudonymize, or omit optional URIs. |
| Valid placement evidence is replayed onto another run or treated as permission | V2 binds each descriptor to `SHA256(RFC8785(runId))`, fixes its authority to `observation-only`, and rejects mismatches before Passport creation. | A compromised producer can still create false but internally consistent observations; authenticate and qualify producers externally. |
| A successful StageFabric observation smuggles a terminal failure or arbitrary HTTP status | A closed AJV union admits only `completed` events or pre-output retries with status `429`, `502`, `503`, or `504`; static types encode the same discriminated contract. | A future producer-contract change requires an explicit, versioned adapter update. |
| An external observation is backdated, postdates its report, or is reserialized behind its URI | The binding carries normalized `observedAt`; report chronology includes it; the StageFabric adapter verifies the producer timestamp grammar and hashes exact canonical writer bytes including LF. | Dates are self-asserted unless the producer is authenticated and backed by trusted time. Availability of the URI remains external. |
| A report claims success after checks are removed, reordered, duplicated, or changed | Creation requires unique ordered check identifiers, binds that order to `rulesDigest`, and derives report status from the checks. | Hash consistency does not authenticate the evaluator or its implementation. |
| A report or Passport appears to predate evidence it assesses | Creation requires report generation after every included observed evidence timestamp and issuance after report generation. | These are self-asserted consistency checks, not trusted timestamps; non-repudiation requires external infrastructure. |
Expand Down
11 changes: 9 additions & 2 deletions scripts/package-smoke.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ try {
'const report = runConformance(result.bundle, "enterprise");',
'const sha256 = (value) => `sha256:${digestValue(value)}`;',
'const identity = { stageIdDigest: sha256("stage"), targetIdDigest: sha256("target"), zoneDigest: sha256("zone"), adapterKindDigest: sha256("adapter") };',
'const unsigned = { apiVersion: "stagefabric.dev/v1alpha1", kind: "ExecutionPlacementEvidence", producer: "stagefabric", disclosure: "content-free", authority: "observation-only", runIdDigest: sha256(result.bundle.execution.runId), observedAt: "2026-07-17T12:00:00.000Z", planDigest: sha256("plan"), bindingDigest: sha256("binding"), snapshotDigest: sha256("snapshot"), egressDigest: sha256("egress"), placements: [{ ...identity, attempt: 1, status: "succeeded", reasonCode: "completed" }], trace: [{ ...identity, attempt: 1, status: "succeeded", reasonCode: "completed" }] };',
'const unsigned = { apiVersion: "stagefabric.dev/v1alpha1", kind: "ExecutionPlacementEvidence", producer: "stagefabric", disclosure: "content-free", authority: "observation-only", runIdDigest: sha256(result.bundle.execution.runId), observedAt: "2026-07-17T12:00:00.000Z", planDigest: sha256("plan"), bindingDigest: sha256("binding"), snapshotDigest: sha256("snapshot"), egressDigest: sha256("egress"), placements: [{ ...identity, attempt: 2, status: "succeeded", reasonCode: "completed" }], trace: [{ ...identity, attempt: 1, status: "failed", reasonCode: "retryable_pre_output_status", statusCode: 503 }, { ...identity, attempt: 2, status: "succeeded", reasonCode: "completed" }] };',
'const executionEvidence = createStageFabricExecutionEvidenceBinding({ ...unsigned, digest: sha256(unsigned) });',
'const passport = createExecutionPassport({ bundle: result.bundle, report, oasfRecord: { opaqueExternalRecord: true }, oasfMediaType: "application/json", executionEvidence: [executionEvidence] });',
'if (report.status !== "pass" || report.runStatus !== "completed" || result.readBack !== true || !validateDocument(passport).valid || passport.subject.length !== 3 || passport.predicate.executionEvidence.length !== 1) process.exit(2);',
Expand Down Expand Up @@ -93,12 +93,19 @@ try {
snapshotDigest: sha256("snapshot"),
egressDigest: sha256("egress"),
placements: [
{ ...identity, attempt: 1, status: "succeeded", reasonCode: "completed" }
{ ...identity, attempt: 2, status: "succeeded", reasonCode: "completed" }
],
trace: [
{
...identity,
attempt: 1,
status: "failed",
reasonCode: "retryable_pre_output_status",
statusCode: 503
},
{
...identity,
attempt: 2,
status: "succeeded",
reasonCode: "completed"
}
Expand Down
Loading
Loading