Wait within decision validity bounds and preserve failed preflight evidence
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a09cbb-87c6-7900-a145-4ce53ba9f1a6
This commit is contained in:
parent
1c9fd5279c
commit
5aaa49a2ec
7 changed files with 647 additions and 1 deletions
|
|
@ -18,7 +18,7 @@
|
||||||
| workplan | SECRETS-WP-0007 | active | — | workplans/SECRETS-WP-0007-production-lifecycle-hardening.md |
|
| workplan | SECRETS-WP-0007 | active | — | workplans/SECRETS-WP-0007-production-lifecycle-hardening.md |
|
||||||
| workplan | SECRETS-WP-0008 | active | — | workplans/SECRETS-WP-0008-layer-model-lifecycle-conformance.md |
|
| workplan | SECRETS-WP-0008 | active | — | workplans/SECRETS-WP-0008-layer-model-lifecycle-conformance.md |
|
||||||
| workplan | SECRETS-WP-0009 | blocked | — | workplans/SECRETS-WP-0009-glas-claude-native-delivery.md |
|
| workplan | SECRETS-WP-0009 | blocked | — | workplans/SECRETS-WP-0009-glas-claude-native-delivery.md |
|
||||||
| workplan | SECRETS-WP-0010 | blocked | — | workplans/SECRETS-WP-0010-openrouter-native-access.md |
|
| workplan | SECRETS-WP-0010 | active | — | workplans/SECRETS-WP-0010-openrouter-native-access.md |
|
||||||
| task | SECRETS-WP-ADHOC-2026-08-21-T01 | done | — | workplans/ADHOC-2026-08-21.md |
|
| task | SECRETS-WP-ADHOC-2026-08-21-T01 | done | — | workplans/ADHOC-2026-08-21.md |
|
||||||
| task | SECRETS-WP-ADHOC-2026-08-23-T01 | done | — | workplans/ADHOC-2026-08-23.md |
|
| task | SECRETS-WP-ADHOC-2026-08-23-T01 | done | — | workplans/ADHOC-2026-08-23.md |
|
||||||
| task | SECRETS-WP-0001-T01 | done | — | workplans/SECRETS-WP-0001-statehub-bootstrap.md |
|
| task | SECRETS-WP-0001-T01 | done | — | workplans/SECRETS-WP-0001-statehub-bootstrap.md |
|
||||||
|
|
|
||||||
|
|
@ -199,3 +199,11 @@ The catalog CCR reference remains provenance; the native path does not demand a
|
||||||
second hub decision or local fixture with that CCR identifier. Unserved legacy
|
second hub decision or local fixture with that CCR identifier. Unserved legacy
|
||||||
build/test paths retain their existing review gate. Claim, PDP, human-control,
|
build/test paths retain their existing review gate. Claim, PDP, human-control,
|
||||||
stance, freshness and consume refusals still prevent backend access.
|
stance, freshness and consume refusals still prevent backend access.
|
||||||
|
|
||||||
|
|
||||||
|
A future `not_before` is now awaited for at most two seconds before full decision
|
||||||
|
validation. Larger skew refuses. Expiry and claim freshness are checked afterward;
|
||||||
|
the consumer never shifts its validation clock or treats a future decision as
|
||||||
|
already valid. Native preflight exposed workstation clock drift; the existing
|
||||||
|
NTP service was restarted. All three owner-store/native-PDP diagnostic joins
|
||||||
|
passed afterward, without consuming approvals. Full regression suite: 420 passed.
|
||||||
|
|
|
||||||
557
docs/evidence/2026-09-14-t03-join-preflight.json
Normal file
557
docs/evidence/2026-09-14-t03-join-preflight.json
Normal file
|
|
@ -0,0 +1,557 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"action": "apply",
|
||||||
|
"scope": "read-only owner-store claim and native PDP diagnosis; not authenticated claim/consume execution",
|
||||||
|
"claim_valid_now": true,
|
||||||
|
"claim_reason": "ok",
|
||||||
|
"effect": "allow",
|
||||||
|
"reason": "catalog_lane_policy_matched",
|
||||||
|
"binding": {
|
||||||
|
"tenant": "tenant:platform",
|
||||||
|
"subject": {
|
||||||
|
"id": "secrets-engine",
|
||||||
|
"type": "service",
|
||||||
|
"tenant": "tenant:platform",
|
||||||
|
"attributes": {
|
||||||
|
"description": "secrets-engine's own service identity, the single calling identity for the twelve gated catalog-lane actions it sends to POST /v1/check. Because it is the only subject, the package has no action_not_granted branch (FLEX-WP-0021-T02); registering a second identity is the revisit trigger.",
|
||||||
|
"display_name": "secrets-engine service principal",
|
||||||
|
"groups": [
|
||||||
|
"group:secrets-engine-lane-operators"
|
||||||
|
],
|
||||||
|
"organization_relation": "ServiceProvider",
|
||||||
|
"roles": [
|
||||||
|
"Operator"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"action": "apply",
|
||||||
|
"resource": {
|
||||||
|
"id": "catalog:openrouter-llm-connect",
|
||||||
|
"type": "secret-catalog-lane",
|
||||||
|
"system": "secrets-engine",
|
||||||
|
"tenant": "tenant:platform",
|
||||||
|
"attributes": {
|
||||||
|
"auth_targets": [
|
||||||
|
"se-prod-openrouter-llm-connect"
|
||||||
|
],
|
||||||
|
"fields": [],
|
||||||
|
"policy_targets": [
|
||||||
|
"se-prod-openrouter-llm-connect"
|
||||||
|
],
|
||||||
|
"stage": "prod"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"context": {
|
||||||
|
"approval": {
|
||||||
|
"approval_id": "09592588-ab15-53e7-89b8-c4e9f29aaacf",
|
||||||
|
"binding": {
|
||||||
|
"action": "apply",
|
||||||
|
"actor": "secrets-engine",
|
||||||
|
"digest": "sha256:03cc5b37437f14e86b686ce4054f976556334eff3fa260b03e8014ed3d9217e5",
|
||||||
|
"human_control": true,
|
||||||
|
"pdp_digest": "sha256:933427642c58c54f65dd4781b8e4c8e2f358eb96497ae35870fff4bd593d2b84",
|
||||||
|
"pdp_path": true,
|
||||||
|
"principal": "secrets-engine",
|
||||||
|
"purpose": "IR-WP-0004 read-only OpenRouter key authentication check; no inference",
|
||||||
|
"target": {
|
||||||
|
"attributes": {
|
||||||
|
"auth_targets": [
|
||||||
|
"se-prod-openrouter-llm-connect"
|
||||||
|
],
|
||||||
|
"fields": [],
|
||||||
|
"policy_targets": [
|
||||||
|
"se-prod-openrouter-llm-connect"
|
||||||
|
],
|
||||||
|
"stage": "prod"
|
||||||
|
},
|
||||||
|
"id": "catalog:openrouter-llm-connect",
|
||||||
|
"system": "secrets-engine",
|
||||||
|
"type": "secret-catalog-lane"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"consumed": false,
|
||||||
|
"freshness": {
|
||||||
|
"not_after": "2026-09-14T01:43:41+00:00",
|
||||||
|
"observed_at": "2026-09-14T01:43:11+00:00",
|
||||||
|
"ttl_seconds": 30
|
||||||
|
},
|
||||||
|
"issuer": "approval-engine",
|
||||||
|
"kind": "approval-claim",
|
||||||
|
"reason_code": "ok",
|
||||||
|
"schema_version": "0.1",
|
||||||
|
"state": "valid",
|
||||||
|
"valid_now": true,
|
||||||
|
"validity": {
|
||||||
|
"expires_at": "2026-09-15T00:33:06.559689+00:00",
|
||||||
|
"not_before": "2026-09-14T00:33:06.559689+00:00"
|
||||||
|
},
|
||||||
|
"yields_to": "net-kingdom taxonomy request-claim schema (statute \u00a717; unassigned)"
|
||||||
|
},
|
||||||
|
"catalog_target": {
|
||||||
|
"auth_capability": {},
|
||||||
|
"consumers": [
|
||||||
|
{
|
||||||
|
"auth": "kubernetes",
|
||||||
|
"claim": "serviceaccount:external-secrets/external-secrets",
|
||||||
|
"name": "llm-connect-activity-core",
|
||||||
|
"purpose": "sync llm-connect-provider-secrets for the activity-core deployment"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"auth": "approle",
|
||||||
|
"claim": "catalog:openrouter-llm-connect",
|
||||||
|
"name": "intelligence-radar-key-check",
|
||||||
|
"purpose": "IR-WP-0004 read-only OpenRouter key authentication check; no inference"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"delivery_auth": {
|
||||||
|
"management": "engine",
|
||||||
|
"method": "approle",
|
||||||
|
"policy_name": "se-prod-openrouter-llm-connect",
|
||||||
|
"role_name": "se-prod-openrouter-llm-connect",
|
||||||
|
"secret_id_num_uses": 1,
|
||||||
|
"secret_id_ttl": "15m",
|
||||||
|
"token_max_ttl": "30m",
|
||||||
|
"token_num_uses": 8,
|
||||||
|
"token_ttl": "15m"
|
||||||
|
},
|
||||||
|
"delivery_config": {
|
||||||
|
"exec_owner": {
|
||||||
|
"command": [
|
||||||
|
"/usr/bin/python3.12",
|
||||||
|
"-I",
|
||||||
|
"-B",
|
||||||
|
"/home/worsch/.local/share/secrets-engine/recipients/openrouter-key-check-dc1569f63ef7/openrouter_key_check.py"
|
||||||
|
],
|
||||||
|
"cwd": "/run/user/1000/secrets-engine-openrouter-check",
|
||||||
|
"environment": {
|
||||||
|
"LANG": "C.UTF-8"
|
||||||
|
},
|
||||||
|
"files": {
|
||||||
|
"/home/worsch/.local/share/secrets-engine/recipients/openrouter-key-check-dc1569f63ef7/openrouter_key_check.py": {
|
||||||
|
"private": true,
|
||||||
|
"sha256": "dc1569f63ef74d73f0a735548c0573db2a1493f7ffc86945f52d0be9b27a3253"
|
||||||
|
},
|
||||||
|
"/usr/bin/python3.12": {
|
||||||
|
"private": false,
|
||||||
|
"sha256": "e50d468e8b0adfb05733f5b87b3cff34829c4a8c1aea50c865aa8bdfe4bb150f"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"owner": "intelligence-radar-key-check",
|
||||||
|
"status": "configured"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"delivery_modes": [
|
||||||
|
"exec-env",
|
||||||
|
"read-check"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
"OPENROUTER_API_KEY"
|
||||||
|
],
|
||||||
|
"kind": "kv",
|
||||||
|
"mount": "platform",
|
||||||
|
"mount_management": "existing",
|
||||||
|
"org": "coulomb",
|
||||||
|
"path": "workloads/activity-core/llm-connect/llm-connect-provider-secrets",
|
||||||
|
"repo": "llm-connect",
|
||||||
|
"workload_delivery": [
|
||||||
|
{
|
||||||
|
"mode": "external-secrets",
|
||||||
|
"owner": "railiance-platform + llm-connect"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"human_control": true,
|
||||||
|
"purpose": "IR-WP-0004 read-only OpenRouter key authentication check; no inference"
|
||||||
|
},
|
||||||
|
"request_digest": "sha256:1e2a0b721dca7a8e719a5837fd4e298be11be4c66535a0f40e11f2fa0639f9df",
|
||||||
|
"approval_binding_digest": "sha256:933427642c58c54f65dd4781b8e4c8e2f358eb96497ae35870fff4bd593d2b84",
|
||||||
|
"submitted_request_digest": "sha256:9241fdc373759d67b8db7c356730714e784804465f1a18d7c12a91bd200f3517"
|
||||||
|
},
|
||||||
|
"provenance": {
|
||||||
|
"evaluator": "flex-auth/local",
|
||||||
|
"mode": "standalone",
|
||||||
|
"policy_package": "secrets-engine.catalog-lane.lifecycle",
|
||||||
|
"policy_version": "v2",
|
||||||
|
"policy_package_digest": "sha256:bd11c5fe77ce6439c65fea225ad6b71d2110efc5e7b5bc9b499c59cd0a53b8b4",
|
||||||
|
"registry_snapshot_digest": "sha256:f5a309bc0b36721fd6d9ad7f53eb21222162bc2eac62a0ab0802a9a1d51340bb",
|
||||||
|
"input_claim_digests": {
|
||||||
|
"context": "sha256:eb41f86373ada6e123049610c1722116b1638d597069b460b2d0b3538b868a60"
|
||||||
|
},
|
||||||
|
"decision_time": "2026-09-14T01:43:11Z"
|
||||||
|
},
|
||||||
|
"validated": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"action": "verify",
|
||||||
|
"scope": "read-only owner-store claim and native PDP diagnosis; not authenticated claim/consume execution",
|
||||||
|
"claim_valid_now": true,
|
||||||
|
"claim_reason": "ok",
|
||||||
|
"effect": "allow",
|
||||||
|
"reason": "catalog_lane_policy_matched",
|
||||||
|
"binding": {
|
||||||
|
"tenant": "tenant:platform",
|
||||||
|
"subject": {
|
||||||
|
"id": "secrets-engine",
|
||||||
|
"type": "service",
|
||||||
|
"tenant": "tenant:platform",
|
||||||
|
"attributes": {
|
||||||
|
"description": "secrets-engine's own service identity, the single calling identity for the twelve gated catalog-lane actions it sends to POST /v1/check. Because it is the only subject, the package has no action_not_granted branch (FLEX-WP-0021-T02); registering a second identity is the revisit trigger.",
|
||||||
|
"display_name": "secrets-engine service principal",
|
||||||
|
"groups": [
|
||||||
|
"group:secrets-engine-lane-operators"
|
||||||
|
],
|
||||||
|
"organization_relation": "ServiceProvider",
|
||||||
|
"roles": [
|
||||||
|
"Operator"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"action": "verify",
|
||||||
|
"resource": {
|
||||||
|
"id": "catalog:openrouter-llm-connect",
|
||||||
|
"type": "secret-catalog-lane",
|
||||||
|
"system": "secrets-engine",
|
||||||
|
"tenant": "tenant:platform",
|
||||||
|
"attributes": {
|
||||||
|
"auth_targets": [
|
||||||
|
"se-prod-openrouter-llm-connect"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
"OPENROUTER_API_KEY"
|
||||||
|
],
|
||||||
|
"policy_targets": [
|
||||||
|
"se-prod-openrouter-llm-connect"
|
||||||
|
],
|
||||||
|
"stage": "prod"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"context": {
|
||||||
|
"approval": {
|
||||||
|
"approval_id": "9416fa31-fa9e-5603-8289-f35bc9625409",
|
||||||
|
"binding": {
|
||||||
|
"action": "verify",
|
||||||
|
"actor": "secrets-engine",
|
||||||
|
"digest": "sha256:72d9267d038c17107c880ffc9009793ce9c70defbddfe2219628854b811a04b2",
|
||||||
|
"human_control": true,
|
||||||
|
"pdp_digest": "sha256:9e36cdbf3890cc5a7e550fd57191f9c0f2a6b2180909aac302aa3b999e7e6b25",
|
||||||
|
"pdp_path": true,
|
||||||
|
"principal": "secrets-engine",
|
||||||
|
"purpose": "IR-WP-0004 read-only OpenRouter key authentication check; no inference",
|
||||||
|
"target": {
|
||||||
|
"attributes": {
|
||||||
|
"auth_targets": [
|
||||||
|
"se-prod-openrouter-llm-connect"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
"OPENROUTER_API_KEY"
|
||||||
|
],
|
||||||
|
"policy_targets": [
|
||||||
|
"se-prod-openrouter-llm-connect"
|
||||||
|
],
|
||||||
|
"stage": "prod"
|
||||||
|
},
|
||||||
|
"id": "catalog:openrouter-llm-connect",
|
||||||
|
"system": "secrets-engine",
|
||||||
|
"type": "secret-catalog-lane"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"consumed": false,
|
||||||
|
"freshness": {
|
||||||
|
"not_after": "2026-09-14T01:43:43+00:00",
|
||||||
|
"observed_at": "2026-09-14T01:43:13+00:00",
|
||||||
|
"ttl_seconds": 30
|
||||||
|
},
|
||||||
|
"issuer": "approval-engine",
|
||||||
|
"kind": "approval-claim",
|
||||||
|
"reason_code": "ok",
|
||||||
|
"schema_version": "0.1",
|
||||||
|
"state": "valid",
|
||||||
|
"valid_now": true,
|
||||||
|
"validity": {
|
||||||
|
"expires_at": "2026-09-15T00:33:06.722887+00:00",
|
||||||
|
"not_before": "2026-09-14T00:33:06.722887+00:00"
|
||||||
|
},
|
||||||
|
"yields_to": "net-kingdom taxonomy request-claim schema (statute \u00a717; unassigned)"
|
||||||
|
},
|
||||||
|
"catalog_target": {
|
||||||
|
"auth_capability": {},
|
||||||
|
"consumers": [
|
||||||
|
{
|
||||||
|
"auth": "kubernetes",
|
||||||
|
"claim": "serviceaccount:external-secrets/external-secrets",
|
||||||
|
"name": "llm-connect-activity-core",
|
||||||
|
"purpose": "sync llm-connect-provider-secrets for the activity-core deployment"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"auth": "approle",
|
||||||
|
"claim": "catalog:openrouter-llm-connect",
|
||||||
|
"name": "intelligence-radar-key-check",
|
||||||
|
"purpose": "IR-WP-0004 read-only OpenRouter key authentication check; no inference"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"delivery_auth": {
|
||||||
|
"management": "engine",
|
||||||
|
"method": "approle",
|
||||||
|
"policy_name": "se-prod-openrouter-llm-connect",
|
||||||
|
"role_name": "se-prod-openrouter-llm-connect",
|
||||||
|
"secret_id_num_uses": 1,
|
||||||
|
"secret_id_ttl": "15m",
|
||||||
|
"token_max_ttl": "30m",
|
||||||
|
"token_num_uses": 8,
|
||||||
|
"token_ttl": "15m"
|
||||||
|
},
|
||||||
|
"delivery_config": {
|
||||||
|
"exec_owner": {
|
||||||
|
"command": [
|
||||||
|
"/usr/bin/python3.12",
|
||||||
|
"-I",
|
||||||
|
"-B",
|
||||||
|
"/home/worsch/.local/share/secrets-engine/recipients/openrouter-key-check-dc1569f63ef7/openrouter_key_check.py"
|
||||||
|
],
|
||||||
|
"cwd": "/run/user/1000/secrets-engine-openrouter-check",
|
||||||
|
"environment": {
|
||||||
|
"LANG": "C.UTF-8"
|
||||||
|
},
|
||||||
|
"files": {
|
||||||
|
"/home/worsch/.local/share/secrets-engine/recipients/openrouter-key-check-dc1569f63ef7/openrouter_key_check.py": {
|
||||||
|
"private": true,
|
||||||
|
"sha256": "dc1569f63ef74d73f0a735548c0573db2a1493f7ffc86945f52d0be9b27a3253"
|
||||||
|
},
|
||||||
|
"/usr/bin/python3.12": {
|
||||||
|
"private": false,
|
||||||
|
"sha256": "e50d468e8b0adfb05733f5b87b3cff34829c4a8c1aea50c865aa8bdfe4bb150f"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"owner": "intelligence-radar-key-check",
|
||||||
|
"status": "configured"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"delivery_modes": [
|
||||||
|
"exec-env",
|
||||||
|
"read-check"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
"OPENROUTER_API_KEY"
|
||||||
|
],
|
||||||
|
"kind": "kv",
|
||||||
|
"mount": "platform",
|
||||||
|
"mount_management": "existing",
|
||||||
|
"org": "coulomb",
|
||||||
|
"path": "workloads/activity-core/llm-connect/llm-connect-provider-secrets",
|
||||||
|
"repo": "llm-connect",
|
||||||
|
"workload_delivery": [
|
||||||
|
{
|
||||||
|
"mode": "external-secrets",
|
||||||
|
"owner": "railiance-platform + llm-connect"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"human_control": true,
|
||||||
|
"purpose": "IR-WP-0004 read-only OpenRouter key authentication check; no inference"
|
||||||
|
},
|
||||||
|
"request_digest": "sha256:9e9f8b506b94fb3d0351b2129f6804f09bc8f207230b636da2112ff722005ab9",
|
||||||
|
"approval_binding_digest": "sha256:9e36cdbf3890cc5a7e550fd57191f9c0f2a6b2180909aac302aa3b999e7e6b25",
|
||||||
|
"submitted_request_digest": "sha256:ae7fdd0a04e2d1f131cbe8e384357aa0f994ab325032b8ff2322aba4532111c7"
|
||||||
|
},
|
||||||
|
"provenance": {
|
||||||
|
"evaluator": "flex-auth/local",
|
||||||
|
"mode": "standalone",
|
||||||
|
"policy_package": "secrets-engine.catalog-lane.lifecycle",
|
||||||
|
"policy_version": "v2",
|
||||||
|
"policy_package_digest": "sha256:bd11c5fe77ce6439c65fea225ad6b71d2110efc5e7b5bc9b499c59cd0a53b8b4",
|
||||||
|
"registry_snapshot_digest": "sha256:f5a309bc0b36721fd6d9ad7f53eb21222162bc2eac62a0ab0802a9a1d51340bb",
|
||||||
|
"input_claim_digests": {
|
||||||
|
"context": "sha256:418548cb749db472a28010fdd9dbb2a20a1c6fdd35b3d756fac6c7a7abc306fe"
|
||||||
|
},
|
||||||
|
"decision_time": "2026-09-14T01:43:13Z"
|
||||||
|
},
|
||||||
|
"validated": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"action": "exec",
|
||||||
|
"scope": "read-only owner-store claim and native PDP diagnosis; not authenticated claim/consume execution",
|
||||||
|
"claim_valid_now": true,
|
||||||
|
"claim_reason": "ok",
|
||||||
|
"effect": "allow",
|
||||||
|
"reason": "catalog_lane_policy_matched",
|
||||||
|
"binding": {
|
||||||
|
"tenant": "tenant:platform",
|
||||||
|
"subject": {
|
||||||
|
"id": "secrets-engine",
|
||||||
|
"type": "service",
|
||||||
|
"tenant": "tenant:platform",
|
||||||
|
"attributes": {
|
||||||
|
"description": "secrets-engine's own service identity, the single calling identity for the twelve gated catalog-lane actions it sends to POST /v1/check. Because it is the only subject, the package has no action_not_granted branch (FLEX-WP-0021-T02); registering a second identity is the revisit trigger.",
|
||||||
|
"display_name": "secrets-engine service principal",
|
||||||
|
"groups": [
|
||||||
|
"group:secrets-engine-lane-operators"
|
||||||
|
],
|
||||||
|
"organization_relation": "ServiceProvider",
|
||||||
|
"roles": [
|
||||||
|
"Operator"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"action": "exec",
|
||||||
|
"resource": {
|
||||||
|
"id": "catalog:openrouter-llm-connect",
|
||||||
|
"type": "secret-catalog-lane",
|
||||||
|
"system": "secrets-engine",
|
||||||
|
"tenant": "tenant:platform",
|
||||||
|
"attributes": {
|
||||||
|
"auth_targets": [
|
||||||
|
"se-prod-openrouter-llm-connect"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
"OPENROUTER_API_KEY"
|
||||||
|
],
|
||||||
|
"policy_targets": [
|
||||||
|
"se-prod-openrouter-llm-connect"
|
||||||
|
],
|
||||||
|
"stage": "prod"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"context": {
|
||||||
|
"approval": {
|
||||||
|
"approval_id": "da678b61-35be-598e-8d95-a7aefa2fdc73",
|
||||||
|
"binding": {
|
||||||
|
"action": "exec",
|
||||||
|
"actor": "secrets-engine",
|
||||||
|
"digest": "sha256:f2cf0fb53b740900756ccde5587c3578fcff44beef2f1edab17b9a198a4033d8",
|
||||||
|
"human_control": true,
|
||||||
|
"pdp_digest": "sha256:9f17812750fc8962b0fc58fc09df136850c9935a864fafa998a1c030dfb75bd9",
|
||||||
|
"pdp_path": true,
|
||||||
|
"principal": "secrets-engine",
|
||||||
|
"purpose": "IR-WP-0004 read-only OpenRouter key authentication check; no inference",
|
||||||
|
"target": {
|
||||||
|
"attributes": {
|
||||||
|
"auth_targets": [
|
||||||
|
"se-prod-openrouter-llm-connect"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
"OPENROUTER_API_KEY"
|
||||||
|
],
|
||||||
|
"policy_targets": [
|
||||||
|
"se-prod-openrouter-llm-connect"
|
||||||
|
],
|
||||||
|
"stage": "prod"
|
||||||
|
},
|
||||||
|
"id": "catalog:openrouter-llm-connect",
|
||||||
|
"system": "secrets-engine",
|
||||||
|
"type": "secret-catalog-lane"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"consumed": false,
|
||||||
|
"freshness": {
|
||||||
|
"not_after": "2026-09-14T01:43:46+00:00",
|
||||||
|
"observed_at": "2026-09-14T01:43:16+00:00",
|
||||||
|
"ttl_seconds": 30
|
||||||
|
},
|
||||||
|
"issuer": "approval-engine",
|
||||||
|
"kind": "approval-claim",
|
||||||
|
"reason_code": "ok",
|
||||||
|
"schema_version": "0.1",
|
||||||
|
"state": "valid",
|
||||||
|
"valid_now": true,
|
||||||
|
"validity": {
|
||||||
|
"expires_at": "2026-09-15T00:33:06.955168+00:00",
|
||||||
|
"not_before": "2026-09-14T00:33:06.955168+00:00"
|
||||||
|
},
|
||||||
|
"yields_to": "net-kingdom taxonomy request-claim schema (statute \u00a717; unassigned)"
|
||||||
|
},
|
||||||
|
"catalog_target": {
|
||||||
|
"auth_capability": {},
|
||||||
|
"consumers": [
|
||||||
|
{
|
||||||
|
"auth": "kubernetes",
|
||||||
|
"claim": "serviceaccount:external-secrets/external-secrets",
|
||||||
|
"name": "llm-connect-activity-core",
|
||||||
|
"purpose": "sync llm-connect-provider-secrets for the activity-core deployment"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"auth": "approle",
|
||||||
|
"claim": "catalog:openrouter-llm-connect",
|
||||||
|
"name": "intelligence-radar-key-check",
|
||||||
|
"purpose": "IR-WP-0004 read-only OpenRouter key authentication check; no inference"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"delivery_auth": {
|
||||||
|
"management": "engine",
|
||||||
|
"method": "approle",
|
||||||
|
"policy_name": "se-prod-openrouter-llm-connect",
|
||||||
|
"role_name": "se-prod-openrouter-llm-connect",
|
||||||
|
"secret_id_num_uses": 1,
|
||||||
|
"secret_id_ttl": "15m",
|
||||||
|
"token_max_ttl": "30m",
|
||||||
|
"token_num_uses": 8,
|
||||||
|
"token_ttl": "15m"
|
||||||
|
},
|
||||||
|
"delivery_config": {
|
||||||
|
"exec_owner": {
|
||||||
|
"command": [
|
||||||
|
"/usr/bin/python3.12",
|
||||||
|
"-I",
|
||||||
|
"-B",
|
||||||
|
"/home/worsch/.local/share/secrets-engine/recipients/openrouter-key-check-dc1569f63ef7/openrouter_key_check.py"
|
||||||
|
],
|
||||||
|
"cwd": "/run/user/1000/secrets-engine-openrouter-check",
|
||||||
|
"environment": {
|
||||||
|
"LANG": "C.UTF-8"
|
||||||
|
},
|
||||||
|
"files": {
|
||||||
|
"/home/worsch/.local/share/secrets-engine/recipients/openrouter-key-check-dc1569f63ef7/openrouter_key_check.py": {
|
||||||
|
"private": true,
|
||||||
|
"sha256": "dc1569f63ef74d73f0a735548c0573db2a1493f7ffc86945f52d0be9b27a3253"
|
||||||
|
},
|
||||||
|
"/usr/bin/python3.12": {
|
||||||
|
"private": false,
|
||||||
|
"sha256": "e50d468e8b0adfb05733f5b87b3cff34829c4a8c1aea50c865aa8bdfe4bb150f"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"owner": "intelligence-radar-key-check",
|
||||||
|
"status": "configured"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"delivery_modes": [
|
||||||
|
"exec-env",
|
||||||
|
"read-check"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
"OPENROUTER_API_KEY"
|
||||||
|
],
|
||||||
|
"kind": "kv",
|
||||||
|
"mount": "platform",
|
||||||
|
"mount_management": "existing",
|
||||||
|
"org": "coulomb",
|
||||||
|
"path": "workloads/activity-core/llm-connect/llm-connect-provider-secrets",
|
||||||
|
"repo": "llm-connect",
|
||||||
|
"workload_delivery": [
|
||||||
|
{
|
||||||
|
"mode": "external-secrets",
|
||||||
|
"owner": "railiance-platform + llm-connect"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"exec_owner_sha256": "22393c7e751e458fa64bb24305ee66a26bbe3993c5aba03ae1fc1a488e777b42",
|
||||||
|
"human_control": true,
|
||||||
|
"purpose": "IR-WP-0004 read-only OpenRouter key authentication check; no inference"
|
||||||
|
},
|
||||||
|
"request_digest": "sha256:0d18ec993f609e9fcaa0d0b18314d1cbfd10e5e16176748f0c21abbd3bf27c51",
|
||||||
|
"approval_binding_digest": "sha256:9f17812750fc8962b0fc58fc09df136850c9935a864fafa998a1c030dfb75bd9",
|
||||||
|
"submitted_request_digest": "sha256:1da3ba876912a80bf0df729ab58325d4ec8da2ff3b77f25bd4157a874f6faa06"
|
||||||
|
},
|
||||||
|
"provenance": {
|
||||||
|
"evaluator": "flex-auth/local",
|
||||||
|
"mode": "standalone",
|
||||||
|
"policy_package": "secrets-engine.catalog-lane.lifecycle",
|
||||||
|
"policy_version": "v2",
|
||||||
|
"policy_package_digest": "sha256:bd11c5fe77ce6439c65fea225ad6b71d2110efc5e7b5bc9b499c59cd0a53b8b4",
|
||||||
|
"registry_snapshot_digest": "sha256:f5a309bc0b36721fd6d9ad7f53eb21222162bc2eac62a0ab0802a9a1d51340bb",
|
||||||
|
"input_claim_digests": {
|
||||||
|
"context": "sha256:da1e2a9704eb5aae6a6cc2d24154246221668d2bd293c0e204f5d0c9d4fb8047"
|
||||||
|
},
|
||||||
|
"decision_time": "2026-09-14T01:43:16Z"
|
||||||
|
},
|
||||||
|
"validated": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"status": "failed",
|
||||||
|
"phase": "preflight",
|
||||||
|
"observed_at": "2026-09-14T01:32:29.742409+00:00",
|
||||||
|
"actions": [],
|
||||||
|
"health_before": {
|
||||||
|
"deployment": [
|
||||||
|
{
|
||||||
|
"namespace": "activity-core",
|
||||||
|
"name": "llm-connect",
|
||||||
|
"ready": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"externalsecret": [
|
||||||
|
{
|
||||||
|
"namespace": "activity-core",
|
||||||
|
"name": "llm-connect-provider-secrets",
|
||||||
|
"ready": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"failure_type": "DecisionError",
|
||||||
|
"owner_forwards_closed": true
|
||||||
|
}
|
||||||
|
|
@ -25,6 +25,7 @@ from secrets_engine.decision_check import check_decision
|
||||||
from secrets_engine.authorization import (
|
from secrets_engine.authorization import (
|
||||||
build_action_request,
|
build_action_request,
|
||||||
validate_decision_envelope,
|
validate_decision_envelope,
|
||||||
|
wait_for_decision_start,
|
||||||
)
|
)
|
||||||
from secrets_engine.errors import DecisionError
|
from secrets_engine.errors import DecisionError
|
||||||
from secrets_engine.openbao import read_strict_token_file
|
from secrets_engine.openbao import read_strict_token_file
|
||||||
|
|
@ -312,6 +313,7 @@ def authorize_action(
|
||||||
request=expected_request,
|
request=expected_request,
|
||||||
opener=pdp_opener or urlopen,
|
opener=pdp_opener or urlopen,
|
||||||
)
|
)
|
||||||
|
wait_for_decision_start(envelope)
|
||||||
validated = validate_decision_envelope(
|
validated = validate_decision_envelope(
|
||||||
envelope,
|
envelope,
|
||||||
expected_request,
|
expected_request,
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import copy
|
||||||
import hashlib
|
import hashlib
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
|
import time
|
||||||
import uuid
|
import uuid
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
|
|
@ -399,3 +400,24 @@ def validate_decision_envelope(
|
||||||
request_digest=evaluated,
|
request_digest=evaluated,
|
||||||
submitted_request_digest=submitted,
|
submitted_request_digest=submitted,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def wait_for_decision_start(envelope: object, *, clock=None, sleeper=None) -> None:
|
||||||
|
"""Wait at most two seconds for an owner's future start, never waive it.
|
||||||
|
|
||||||
|
Full decision/claim validation still runs afterward against the real clock.
|
||||||
|
Longer skew refuses rather than holding an approval claim until it is stale.
|
||||||
|
"""
|
||||||
|
current_time = clock or (lambda: datetime.now(timezone.utc))
|
||||||
|
sleep = sleeper or time.sleep
|
||||||
|
if not isinstance(envelope, dict):
|
||||||
|
return
|
||||||
|
lifetime = _required_dict(envelope, "lifetime")
|
||||||
|
if lifetime.get("not_before") is None:
|
||||||
|
return
|
||||||
|
start = _parse_time(lifetime["not_before"], "not_before")
|
||||||
|
delay = (start - current_time()).total_seconds()
|
||||||
|
if delay > 2:
|
||||||
|
raise DecisionError("flex-auth decision start exceeds bounded wait")
|
||||||
|
if delay > 0:
|
||||||
|
sleep(delay)
|
||||||
|
|
|
||||||
33
tests/test_decision_start_wait.py
Normal file
33
tests/test_decision_start_wait.py
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
from datetime import datetime, timedelta, timezone
|
||||||
|
import pytest
|
||||||
|
from secrets_engine.authorization import wait_for_decision_start
|
||||||
|
from secrets_engine.errors import DecisionError
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("offset,expected", [(-1, []), (0, []), (0.25, [0.25]), (2, [2])])
|
||||||
|
def test_waits_until_start_without_changing_the_envelope(offset, expected):
|
||||||
|
now = datetime(2026, 9, 14, tzinfo=timezone.utc)
|
||||||
|
envelope = {"lifetime": {"not_before": (now + timedelta(seconds=offset)).isoformat()}}
|
||||||
|
calls = []
|
||||||
|
wait_for_decision_start(envelope, clock=lambda: now, sleeper=calls.append)
|
||||||
|
assert calls == expected
|
||||||
|
assert envelope["lifetime"]["not_before"] == (now + timedelta(seconds=offset)).isoformat()
|
||||||
|
|
||||||
|
def test_large_skew_refuses_without_sleep():
|
||||||
|
now = datetime(2026, 9, 14, tzinfo=timezone.utc)
|
||||||
|
with pytest.raises(DecisionError, match="bounded wait"):
|
||||||
|
wait_for_decision_start({"lifetime": {"not_before": (now + timedelta(seconds=3)).isoformat()}},
|
||||||
|
clock=lambda: now, sleeper=lambda _: pytest.fail("must not sleep"))
|
||||||
|
|
||||||
|
def test_wait_does_not_waive_expiration_or_start_validation():
|
||||||
|
from secrets_engine.authorization import validate_decision_envelope
|
||||||
|
from tests.test_action_authorization import _envelope, _request
|
||||||
|
request = _request()
|
||||||
|
envelope = _envelope(request)
|
||||||
|
now = datetime(2026, 9, 14, tzinfo=timezone.utc)
|
||||||
|
envelope["lifetime"] = {"not_before": (now + timedelta(seconds=1)).isoformat(),
|
||||||
|
"expires_at": (now + timedelta(seconds=2)).isoformat()}
|
||||||
|
wait_for_decision_start(envelope, clock=lambda: now, sleeper=lambda _: None)
|
||||||
|
with pytest.raises(DecisionError, match="has not started"):
|
||||||
|
validate_decision_envelope(envelope, request, accepted_policy_packages={"secrets-engine.catalog-lane.lifecycle"}, accepted_policy_versions={"v2"}, now=now)
|
||||||
|
with pytest.raises(DecisionError, match="expired"):
|
||||||
|
validate_decision_envelope(envelope, request, accepted_policy_packages={"secrets-engine.catalog-lane.lifecycle"}, accepted_policy_versions={"v2"}, now=now + timedelta(seconds=3))
|
||||||
Loading…
Add table
Add a link
Reference in a new issue