Skip to content
Merged
36 changes: 36 additions & 0 deletions contracts/external-trust-signal-provider.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
]
},
"sha256Digest": {
"type": ["string", "null"],
"type": [
"string",
"null"
Expand Down Expand Up @@ -131,6 +132,13 @@
"failureReason"
],
"properties": {
"providerRef": { "type": "string" },
"signalType": { "$ref": "#/$defs/signalType" },
"signalRef": { "type": "string" },
"signalDigest": { "$ref": "#/$defs/sha256Digest" },
"verifiedAt": { "type": "string" },
"freshness": { "$ref": "#/$defs/freshness" },
"signature": { "$ref": "#/$defs/signature" },
"providerRef": {
"type": "string"
},
Expand All @@ -156,6 +164,8 @@
"type": "string",
"const": "non-authoritative-verifier-input"
},
"failureReason": { "type": ["string", "null"] },
"notes": { "type": "array", "items": { "type": "string" } }
"failureReason": {
"type": [
"string",
Expand Down Expand Up @@ -210,6 +220,8 @@
"signatureRequired"
],
"properties": {
"requestId": { "type": "string" },
"providerRef": { "type": "string" },
"requestId": {
"type": "string"
},
Expand Down Expand Up @@ -306,6 +318,10 @@
"properties": {
"status": {
"type": "string",
"enum": ["available", "unavailable", "stale", "malformed", "unsigned", "denied", "error"]
},
"usableForGrantResolution": { "type": "boolean" },
"providerRef": { "type": "string" },
"enum": [
"available",
"unavailable",
Expand All @@ -326,6 +342,13 @@
"type": "string",
"const": "non-authoritative-verifier-input"
},
"verifiedAt": { "type": ["string", "null"] },
"freshness": { "$ref": "#/$defs/freshness" },
"signals": {
"type": "array",
"items": { "$ref": "#/$defs/externalTrustSignal" }
},
"failureReason": { "type": ["string", "null"] }
"verifiedAt": {
"type": [
"string",
Expand Down Expand Up @@ -379,6 +402,19 @@
"rawUserDataIncluded"
],
"properties": {
"includeRawContent": { "type": "boolean", "const": false },
"rawPromptContentIncluded": { "type": "boolean", "const": false },
"rawKvCacheContentIncluded": { "type": "boolean", "const": false },
"secretValuesIncluded": { "type": "boolean", "const": false },
"privateMemoryIncluded": { "type": "boolean", "const": false },
"apiKeysIncluded": { "type": "boolean", "const": false },
"walletPrivateKeysIncluded": { "type": "boolean", "const": false },
"rawCredentialsIncluded": { "type": "boolean", "const": false },
"rawUserDataIncluded": { "type": "boolean", "const": false }
}
},
"observedAt": { "type": "string" },
"labels": { "type": "object", "additionalProperties": { "type": "string" } }
"includeRawContent": {
"type": "boolean",
"const": false
Expand Down
15 changes: 9 additions & 6 deletions docs/architecture/agent-registry-grants.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ This grant is a local SourceOS control-plane artifact. It may consume external i
AgentPod
-> Policy Fabric admission
-> Agent Registry grant request
-> optional external verifier inputs
-> optional ExternalTrustSignalProvider verifier inputs
-> local grant resolution
-> ActivationDecision
-> runtime placement or fail-closed
Expand Down Expand Up @@ -56,9 +56,11 @@ Allowed scope must be no broader than the requested scope. Denied scope is expli

## External trust signals

External systems can be useful for agent identity verification, reputation, counterparty checks, and certificate-tier claims. They are not the Agent Registry.
External systems can be useful for agent identity verification, reputation, counterparty checks, registry lookup, and certificate-tier claims. They are not the Agent Registry.

When used, external trust signals must be recorded under `grant.externalTrustSignals` with:
`ExternalTrustSignalProvider` artifacts represent those adapter results. A usable result can be considered by the local Agent Registry grant resolver only when it is fresh, signed when signatures are required, scoped to the requested provider and signal types, and marked with `authority: non-authoritative-verifier-input`.

When used inside an `AgentRegistryGrant`, external trust signals must be recorded under `grant.externalTrustSignals` with:

- the provider reference;
- the signal type;
Expand All @@ -67,7 +69,7 @@ When used, external trust signals must be recorded under `grant.externalTrustSig
- verification time;
- `authority: non-authoritative-verifier-input`.

This keeps PCH/ERC-8004-style identity, reputation, and certificate-tier checks pluggable without making any external gateway the SourceOS root of trust.
This keeps PCH/ERC-8004-style identity, reputation, registry lookup, and certificate-tier checks pluggable without making any external gateway the SourceOS root of trust.

## Fail-closed rules

Expand All @@ -79,10 +81,11 @@ Activation fails closed when:
- the requested provider is not present in allowed provider scope;
- required activation tools are absent from allowed tool scope;
- the grant is missing a revocation hook;
- the grant payload includes secrets, raw prompts, raw KV-cache contents, or private memory contents.
- required external trust signals are unavailable, stale, malformed, unsigned when signatures are required, or authority-elevated;
- the grant or external trust payload includes secrets, raw prompts, raw KV-cache contents, private memory contents, API keys, private wallet keys, raw credentials, or raw user data.

## Relation to receipts

`DeploymentReceipt` proves deterministic derivation. `PolicyAdmission` proves policy admission. `AgentRegistryGrant` proves identity/session/tool/provider/storage authorization. `ActivationDecision` combines those inputs and either permits scoped activation or records fail-closed reasons.
`DeploymentReceipt` proves deterministic derivation. `PolicyAdmission` proves policy admission. `ExternalTrustSignalProvider` proves optional verifier-input posture. `AgentRegistryGrant` proves identity/session/tool/provider/storage authorization. `ActivationDecision` combines those inputs and either permits scoped activation or records fail-closed reasons.

None of these artifacts should include raw prompt content, KV-cache contents, secret values, private memory, or raw user data.
2 changes: 2 additions & 0 deletions scripts/validate-package.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ def main() -> int:
raise AssertionError("supply_chain.is_sha256_digest rejected valid digest")
if agent_machine.release_bundle.DEFAULT_REPOSITORY != "SourceOS-Linux/agent-machine":
raise AssertionError("unexpected release_bundle default repository")
if agent_machine.external_trust.AUTHORITY != "non-authoritative-verifier-input":
raise AssertionError("unexpected external trust authority")
if agent_machine.policy_fabric.DEFAULT_DECIDED_AT != "1970-01-01T00:00:00Z":
raise AssertionError("unexpected policy_fabric default decided_at")
if agent_machine.agent_registry.DEFAULT_ISSUED_AT != "1970-01-01T00:00:00Z":
Expand Down
1 change: 1 addition & 0 deletions src/agent_machine/external_trust.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,5 +223,6 @@ def main() -> int:
try:
raise SystemExit(main())
except (AssertionError, RuntimeError) as exc:
print(str(exc), file=__import__("sys").stderr)
print(str(exc), file=sys.stderr)
raise SystemExit(1) from exc
Loading