docs: preserve reviewed NetKingdom session artifacts
This commit is contained in:
parent
a4c1663558
commit
e19bcd1f3d
43 changed files with 11145 additions and 0 deletions
|
|
@ -0,0 +1,90 @@
|
|||
"""Disposable synthetic proof: actual Approval App HTTPS -> actual Access serve.
|
||||
No native config, credential environment, approval or backend effect is used.
|
||||
"""
|
||||
import base64, hashlib, http.server, io, json, os, pathlib, socket, ssl, subprocess, sys, tempfile, threading, time
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from wsgiref.simple_server import make_server, WSGIRequestHandler
|
||||
from cryptography import x509
|
||||
from cryptography.x509.oid import NameOID
|
||||
from cryptography.hazmat.primitives import hashes, serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||
sys.path.insert(0, '/home/worsch/approval-engine')
|
||||
sys.path.insert(0, '/home/worsch/secrets-engine/src')
|
||||
from approval_engine.api import App
|
||||
from approval_engine.auth import Identity, StaticTokenAuthenticator
|
||||
from approval_engine.store import Engine
|
||||
from secrets_engine.authorization import request_digest, approval_binding_digest
|
||||
from urllib.request import Request, urlopen
|
||||
from urllib.error import HTTPError
|
||||
|
||||
OUT=pathlib.Path(sys.argv[1]);OUT.mkdir(exist_ok=True)
|
||||
def digest(raw):return 'sha256:'+hashlib.sha256(raw).hexdigest()
|
||||
def write(path,raw,mode=0o600):path.write_bytes(raw);path.chmod(mode)
|
||||
def identity(subject,kind,scopes):return Identity(subject=subject,issuer='synthetic-test-only',audiences=('approval-engine',),principal_type=kind,tenant='tenant:platform',roles=frozenset(),scopes=frozenset(scopes),assurance={'level':'synthetic'},evidence_ref='synthetic-test-only',tenant_source='directory')
|
||||
class Quiet(WSGIRequestHandler):
|
||||
def log_message(self,*args):pass
|
||||
class Review(http.server.BaseHTTPRequestHandler):
|
||||
def do_POST(self):
|
||||
raw=self.rfile.read(int(self.headers['Content-Length']));body=json.loads(raw)
|
||||
assert self.path=='/apis/authentication.k8s.io/v1/tokenreviews'
|
||||
assert self.headers['Authorization']=='Bearer synthetic-reviewer'
|
||||
assert body['spec']['audiences']==['flex-auth','access-engine']
|
||||
self.send_response(200);self.send_header('Content-Type','application/json');self.end_headers();self.wfile.write(json.dumps({'status':{'authenticated':True,'audiences':['flex-auth'],'user':{'username':'system:serviceaccount:secrets-engine:secrets-engine'}}}).encode())
|
||||
def log_message(self,*args):pass
|
||||
with tempfile.TemporaryDirectory(prefix='access-actual-python-source-') as folder:
|
||||
root=pathlib.Path(folder);now=datetime.now(timezone.utc)
|
||||
key=rsa.generate_private_key(public_exponent=65537,key_size=2048);name=x509.Name([x509.NameAttribute(NameOID.COMMON_NAME,'localhost')]);cert=(x509.CertificateBuilder().subject_name(name).issuer_name(name).public_key(key.public_key()).serial_number(x509.random_serial_number()).not_valid_before(now-timedelta(minutes=1)).not_valid_after(now+timedelta(hours=1)).add_extension(x509.SubjectAlternativeName([x509.DNSName('localhost')]),critical=False).sign(key,hashes.SHA256()))
|
||||
ca=root/'ca.pem';private=root/'tls-key.pem';write(ca,cert.public_bytes(serialization.Encoding.PEM));write(private,key.private_bytes(serialization.Encoding.PEM,serialization.PrivateFormat.PKCS8,serialization.NoEncryption()))
|
||||
tls=ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER);tls.load_cert_chain(ca,private)
|
||||
ctx=ssl.create_default_context(cafile=str(ca))
|
||||
def start(server):server.socket=tls.wrap_socket(server.socket,server_side=True);threading.Thread(target=server.serve_forever,daemon=True).start();return 'https://localhost:'+str(server.server_port)
|
||||
review=http.server.HTTPServer(('127.0.0.1',0),Review);review_origin=start(review)
|
||||
engine=Engine(root/'approval.sqlite3',freshness_ttl=60)
|
||||
auth=StaticTokenAuthenticator({'synthetic-creator':identity('secrets-engine','service',{'approval:create'}),'synthetic-human':identity('synthetic-human','human',{'approval:approve'}),'synthetic-reader':identity('synthetic-access-reader','service',{'approval:read'})})
|
||||
app=App(engine,auth)
|
||||
source=make_server('127.0.0.1',0,app,handler_class=Quiet);origin=start(source)
|
||||
def source_call(method,path,body,token):
|
||||
request=Request(origin+path,data=json.dumps(body).encode() if body is not None else None,method=method,headers={'Authorization':'Bearer '+token,'Content-Type':'application/json'})
|
||||
with urlopen(request,context=ctx,timeout=3) as response:return response.status,json.load(response)
|
||||
# Reuse existing owner interoperability contract generator; it has synthetic metadata only.
|
||||
generated=subprocess.check_output([sys.executable,'/tmp/access-trusted-b2-b3/tools/service_task_execution_fixture.py'],env={'PATH':os.defpath})
|
||||
request=json.loads(generated)['request'];request['subject']['tenant']='tenant:platform';request['resource']['tenant']='tenant:platform';request['context']['purpose']='actual Python App source-only synthetic proof';del request['context']['approval']
|
||||
native={'action':request['action'],'actor':'secrets-engine','principal':'secrets-engine','purpose':request['context']['purpose'],'target':request['resource']}
|
||||
aid='aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee'
|
||||
status,created=source_call('POST','/v1/approvals',{'id':aid,'binding':native,'validity':{'not_before':(now-timedelta(minutes=1)).isoformat(),'expires_at':(now+timedelta(minutes=3)).isoformat()},'required_count':1,'pdp_digest':approval_binding_digest(request),'pdp_path':True,'human_control':True},'synthetic-creator');assert status==201
|
||||
status,_=source_call('POST',f'/v1/approvals/{aid}/entries',{},'synthetic-human');assert status==200
|
||||
status,claim=source_call('GET',f'/v1/approvals/{aid}/claim',None,'synthetic-reader');assert status==200 and claim['valid_now'] is True and claim['binding']['human_control'] is True
|
||||
request['context']['approval']=claim
|
||||
seed=root/'seed';write(seed,base64.urlsafe_b64encode(bytes([19])*32).rstrip(b'='),0o440)
|
||||
reviewer_token=root/'review-token';write(reviewer_token,b'synthetic-reviewer',0o440)
|
||||
reader_token=root/'reader-token';write(reader_token,b'synthetic-reader',0o440)
|
||||
registry=root/'registry.json';write(registry,b'{}')
|
||||
config=root/'source.json';write(config,json.dumps({'source_id':'synthetic-actual-approval-app','source_revision':'actual-owner-python-source-fixture','origin':origin,'store_tenant':'tenant:platform','ca_file':str(ca),'token_file':str(reader_token)}).encode())
|
||||
listener=socket.socket();listener.bind(('127.0.0.1',0));port=listener.getsockname()[1];listener.close()
|
||||
record=root/'record.jsonl';url=f'http://127.0.0.1:{port}'
|
||||
command=['/tmp/netkingdom-access-trusted-r1','serve','--addr',f'127.0.0.1:{port}','--registry',str(registry),'--policy','/tmp/access-trusted-b2-b3/examples/secrets-engine-service-task-execution-v2/policy_package.md','--log',str(record),'--caller-auth-mode','enforce','--caller-audience','flex-auth','--caller-kubernetes-url',review_origin,'--caller-reviewer-token-file',str(reviewer_token),'--caller-ca-file',str(ca),'--caller-binding','secrets-engine=system:serviceaccount:secrets-engine:secrets-engine','--envelope-signing-key-file',str(seed),'--envelope-signing-kid','synthetic-v2','--approval-source-file',str(config)]
|
||||
child=subprocess.Popen(command,env={},stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL)
|
||||
try:
|
||||
for _ in range(100):
|
||||
try:
|
||||
with urlopen(url+'/healthz',timeout=.2):break
|
||||
except Exception:time.sleep(.02)
|
||||
jwt='synthetic.'+base64.urlsafe_b64encode(json.dumps({'exp':int((now+timedelta(minutes=2)).timestamp())}).encode()).decode().rstrip('=')+'.synthetic'
|
||||
def check(value):
|
||||
req=Request(url+'/v1/check',data=json.dumps(value).encode(),headers={'Authorization':'Bearer '+jwt,'Content-Type':'application/json'})
|
||||
try:
|
||||
with urlopen(req,timeout=5) as response:return response.status,response.read()
|
||||
except HTTPError as error:return error.code,error.read()
|
||||
status,raw=check(request);assert status==200,(status,raw)
|
||||
response=json.loads(raw);assert response['effect']=='allow' and response['signature']['mode']=='signed'
|
||||
assert response['binding']['context']==request['context'];assert response['binding']['submitted_request_digest']==request_digest(request);assert response['binding']['approval_binding_digest']==approval_binding_digest(request)
|
||||
assert response['provenance']['approval_observation']['source_id']=='synthetic-actual-approval-app'
|
||||
saved=record.read_bytes();assert json.loads(saved)==response
|
||||
# Actual producer state transition is fetched anew and cannot be rescued by carried claim.
|
||||
engine.revoke(aid)
|
||||
refused,_=check(request);assert refused!=200 and record.read_bytes()==saved
|
||||
for name,value in [('request.json',request),('response.json',response),('source-record.json',json.loads(saved)),('original-approval-claim.json',claim)]:write(OUT/name,(json.dumps(value,indent=2)+'\n').encode(),0o644)
|
||||
receipt={'scope':'disposable synthetic only','actual_source':'Approval App over TLS with authenticated create, configured synthetic human entry, read; actual SQLite engine','actual_access':'production serve binary from frozen B2/B3 R1','allow':True,'original_context_unchanged':True,'published_digest_match':True,'returned_source_record_match':True,'actual_source_revoke_refused':True,'no_record_after_refusal':True,'native_admission':False,'files_sha256':{p.name:digest(p.read_bytes()) for p in OUT.iterdir() if p.suffix=='.json'}}
|
||||
write(OUT/'receipt.json',(json.dumps(receipt,indent=2)+'\n').encode(),0o644);print(json.dumps(receipt,indent=2))
|
||||
finally:
|
||||
child.terminate();child.wait(timeout=5);source.shutdown();review.shutdown();engine.close()
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"approval_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
|
||||
"binding": {
|
||||
"action": "execute-ccr",
|
||||
"actor": "secrets-engine",
|
||||
"digest": "sha256:19cfbe20e156cef1f4c0a37842c47666d2f5b2164d803d77a12346ed38a9444d",
|
||||
"human_control": true,
|
||||
"pdp_digest": "sha256:945b3b5c014370f1a64dbca47c44a5c85124b294b6e6a11e4974c958530aa86b",
|
||||
"pdp_path": true,
|
||||
"principal": "secrets-engine",
|
||||
"purpose": "actual Python App source-only synthetic proof",
|
||||
"target": {
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
},
|
||||
"id": "catalog:synthetic",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"type": "secret-catalog-lane"
|
||||
}
|
||||
},
|
||||
"consumed": false,
|
||||
"freshness": {
|
||||
"not_after": "2026-10-16T09:07:33+00:00",
|
||||
"observed_at": "2026-10-16T09:06:33+00:00",
|
||||
"ttl_seconds": 60
|
||||
},
|
||||
"issuer": "approval-engine",
|
||||
"kind": "approval-claim",
|
||||
"reason_code": "ok",
|
||||
"schema_version": "0.1",
|
||||
"state": "valid",
|
||||
"valid_now": true,
|
||||
"validity": {
|
||||
"expires_at": "2026-10-16T09:09:33.329626+00:00",
|
||||
"not_before": "2026-10-16T09:05:33.329626+00:00"
|
||||
},
|
||||
"yields_to": "net-kingdom taxonomy request-claim schema (statute \u00a717; unassigned)"
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"scope": "disposable synthetic only",
|
||||
"actual_source": "Approval App over TLS with authenticated create, configured synthetic human entry, read; actual SQLite engine",
|
||||
"actual_access": "production serve binary from frozen B2/B3 R1",
|
||||
"allow": true,
|
||||
"original_context_unchanged": true,
|
||||
"published_digest_match": true,
|
||||
"returned_source_record_match": true,
|
||||
"actual_source_revoke_refused": true,
|
||||
"no_record_after_refusal": true,
|
||||
"native_admission": false,
|
||||
"files_sha256": {
|
||||
"source-record.json": "sha256:592b375208d6c2d5add685df0e789b3e0adc0794989712871a518b1a6800e1dc",
|
||||
"response.json": "sha256:592b375208d6c2d5add685df0e789b3e0adc0794989712871a518b1a6800e1dc",
|
||||
"original-approval-claim.json": "sha256:002221b16301dbc61767a926e950dad594bb3e6b6f6c1d9e038deeb56ca9dd83",
|
||||
"request.json": "sha256:47793f3bad156f0b50e8d9bb663c585c5fce779b87a59aac0887b4f2dfe8799f"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
{
|
||||
"tenant": "tenant:platform",
|
||||
"subject": {
|
||||
"id": "secrets-engine",
|
||||
"type": "service",
|
||||
"tenant": "tenant:platform"
|
||||
},
|
||||
"action": "execute-ccr",
|
||||
"resource": {
|
||||
"id": "catalog:synthetic",
|
||||
"type": "secret-catalog-lane",
|
||||
"system": "secrets-engine",
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
},
|
||||
"tenant": "tenant:platform"
|
||||
},
|
||||
"context": {
|
||||
"execution_contract": {
|
||||
"backend_budget": {
|
||||
"ttl_seconds": 120,
|
||||
"uses": 12
|
||||
},
|
||||
"backend_origin": "http://127.0.0.1:18200",
|
||||
"catalog_sha256": "sha256:290e55b2258d66980f9443ba7d1436adfc77b8814bd161004d5af2ba272bc9cc",
|
||||
"ccr_id": "CCR-2099-0001",
|
||||
"ccr_immutable_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"cluster_uid": "synthetic-not-native",
|
||||
"contract_version": "SECRETS-EXEC-20261011-v1",
|
||||
"execution_actor": "service:secrets-engine",
|
||||
"execution_grant_ccr_id": "CCR-2099-0002",
|
||||
"expected_after": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"expected_before": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"grant_immutable_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"operation": "metadata-apply-ccr",
|
||||
"operation_deadline": "2026-10-16T09:08:13.606884+00:00",
|
||||
"operation_id": "cbfbced0-09d5-48c8-a1e7-a2ea4dc69153",
|
||||
"operations": [
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
],
|
||||
"source_bundle": {
|
||||
"engine_dispatcher": {
|
||||
"path": "/synthetic/engine_dispatcher.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"platform_mediator": {
|
||||
"path": "/synthetic/platform_mediator.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"policy_auth": {
|
||||
"path": "/synthetic/policy_auth.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"typed_ccr": {
|
||||
"path": "/synthetic/typed_ccr.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
}
|
||||
},
|
||||
"catalog_target": {
|
||||
"lane": "synthetic",
|
||||
"stage": "prod"
|
||||
},
|
||||
"human_control": true,
|
||||
"service_actor_binding": {
|
||||
"version": "proposed-service-task-caller/v1",
|
||||
"transport_principal": "system:serviceaccount:secrets-engine:secrets-engine",
|
||||
"subject_id": "secrets-engine",
|
||||
"subject_type": "service",
|
||||
"tenant": "tenant:platform"
|
||||
},
|
||||
"purpose": "actual Python App source-only synthetic proof",
|
||||
"approval": {
|
||||
"approval_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
|
||||
"binding": {
|
||||
"action": "execute-ccr",
|
||||
"actor": "secrets-engine",
|
||||
"digest": "sha256:19cfbe20e156cef1f4c0a37842c47666d2f5b2164d803d77a12346ed38a9444d",
|
||||
"human_control": true,
|
||||
"pdp_digest": "sha256:945b3b5c014370f1a64dbca47c44a5c85124b294b6e6a11e4974c958530aa86b",
|
||||
"pdp_path": true,
|
||||
"principal": "secrets-engine",
|
||||
"purpose": "actual Python App source-only synthetic proof",
|
||||
"target": {
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
},
|
||||
"id": "catalog:synthetic",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"type": "secret-catalog-lane"
|
||||
}
|
||||
},
|
||||
"consumed": false,
|
||||
"freshness": {
|
||||
"not_after": "2026-10-16T09:07:33+00:00",
|
||||
"observed_at": "2026-10-16T09:06:33+00:00",
|
||||
"ttl_seconds": 60
|
||||
},
|
||||
"issuer": "approval-engine",
|
||||
"kind": "approval-claim",
|
||||
"reason_code": "ok",
|
||||
"schema_version": "0.1",
|
||||
"state": "valid",
|
||||
"valid_now": true,
|
||||
"validity": {
|
||||
"expires_at": "2026-10-16T09:09:33.329626+00:00",
|
||||
"not_before": "2026-10-16T09:05:33.329626+00:00"
|
||||
},
|
||||
"yields_to": "net-kingdom taxonomy request-claim schema (statute \u00a717; unassigned)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,229 @@
|
|||
{
|
||||
"id": "decision:f85ef006900157fe",
|
||||
"contract_version": "flex-auth.decision-record.v1",
|
||||
"effect": "allow",
|
||||
"reason": "exact_task_execution_matched",
|
||||
"matched_policy_version": "v2",
|
||||
"matched_rule": "exact_task_execution_matched",
|
||||
"resource": {
|
||||
"id": "catalog:synthetic",
|
||||
"type": "secret-catalog-lane",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
}
|
||||
},
|
||||
"subject": {
|
||||
"id": "secrets-engine",
|
||||
"type": "service",
|
||||
"tenant": "tenant:platform"
|
||||
},
|
||||
"binding": {
|
||||
"tenant": "tenant:platform",
|
||||
"subject": {
|
||||
"id": "secrets-engine",
|
||||
"type": "service",
|
||||
"tenant": "tenant:platform"
|
||||
},
|
||||
"action": "execute-ccr",
|
||||
"resource": {
|
||||
"id": "catalog:synthetic",
|
||||
"type": "secret-catalog-lane",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
}
|
||||
},
|
||||
"context": {
|
||||
"approval": {
|
||||
"approval_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
|
||||
"binding": {
|
||||
"action": "execute-ccr",
|
||||
"actor": "secrets-engine",
|
||||
"digest": "sha256:19cfbe20e156cef1f4c0a37842c47666d2f5b2164d803d77a12346ed38a9444d",
|
||||
"human_control": true,
|
||||
"pdp_digest": "sha256:945b3b5c014370f1a64dbca47c44a5c85124b294b6e6a11e4974c958530aa86b",
|
||||
"pdp_path": true,
|
||||
"principal": "secrets-engine",
|
||||
"purpose": "actual Python App source-only synthetic proof",
|
||||
"target": {
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
},
|
||||
"id": "catalog:synthetic",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"type": "secret-catalog-lane"
|
||||
}
|
||||
},
|
||||
"consumed": false,
|
||||
"freshness": {
|
||||
"not_after": "2026-10-16T09:07:33+00:00",
|
||||
"observed_at": "2026-10-16T09:06:33+00:00",
|
||||
"ttl_seconds": 60
|
||||
},
|
||||
"issuer": "approval-engine",
|
||||
"kind": "approval-claim",
|
||||
"reason_code": "ok",
|
||||
"schema_version": "0.1",
|
||||
"state": "valid",
|
||||
"valid_now": true,
|
||||
"validity": {
|
||||
"expires_at": "2026-10-16T09:09:33.329626+00:00",
|
||||
"not_before": "2026-10-16T09:05:33.329626+00:00"
|
||||
},
|
||||
"yields_to": "net-kingdom taxonomy request-claim schema (statute \u00a717; unassigned)"
|
||||
},
|
||||
"catalog_target": {
|
||||
"lane": "synthetic",
|
||||
"stage": "prod"
|
||||
},
|
||||
"execution_contract": {
|
||||
"backend_budget": {
|
||||
"ttl_seconds": 120,
|
||||
"uses": 12
|
||||
},
|
||||
"backend_origin": "http://127.0.0.1:18200",
|
||||
"catalog_sha256": "sha256:290e55b2258d66980f9443ba7d1436adfc77b8814bd161004d5af2ba272bc9cc",
|
||||
"ccr_id": "CCR-2099-0001",
|
||||
"ccr_immutable_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"cluster_uid": "synthetic-not-native",
|
||||
"contract_version": "SECRETS-EXEC-20261011-v1",
|
||||
"execution_actor": "service:secrets-engine",
|
||||
"execution_grant_ccr_id": "CCR-2099-0002",
|
||||
"expected_after": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"expected_before": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"grant_immutable_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"operation": "metadata-apply-ccr",
|
||||
"operation_deadline": "2026-10-16T09:08:13.606884+00:00",
|
||||
"operation_id": "cbfbced0-09d5-48c8-a1e7-a2ea4dc69153",
|
||||
"operations": [
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
],
|
||||
"source_bundle": {
|
||||
"engine_dispatcher": {
|
||||
"path": "/synthetic/engine_dispatcher.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"platform_mediator": {
|
||||
"path": "/synthetic/platform_mediator.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"policy_auth": {
|
||||
"path": "/synthetic/policy_auth.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"typed_ccr": {
|
||||
"path": "/synthetic/typed_ccr.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
}
|
||||
},
|
||||
"human_control": true,
|
||||
"purpose": "actual Python App source-only synthetic proof",
|
||||
"service_actor_binding": {
|
||||
"subject_id": "secrets-engine",
|
||||
"subject_type": "service",
|
||||
"tenant": "tenant:platform",
|
||||
"transport_principal": "system:serviceaccount:secrets-engine:secrets-engine",
|
||||
"version": "proposed-service-task-caller/v1"
|
||||
}
|
||||
},
|
||||
"request_digest": "sha256:18db34b2bad28d655d96ce62e3a0a62bf54f47aea6041f41068b404497fec001",
|
||||
"approval_binding_digest": "sha256:945b3b5c014370f1a64dbca47c44a5c85124b294b6e6a11e4974c958530aa86b",
|
||||
"submitted_request_digest": "sha256:18db34b2bad28d655d96ce62e3a0a62bf54f47aea6041f41068b404497fec001"
|
||||
},
|
||||
"lifetime": {
|
||||
"kind": "ttl",
|
||||
"ttl": "15s",
|
||||
"not_before": "2026-10-16T09:06:33Z",
|
||||
"expires_at": "2026-10-16T09:06:48Z"
|
||||
},
|
||||
"diagnostics": {
|
||||
"action": "execute-ccr",
|
||||
"matched_relationship": "",
|
||||
"policy_package": "secrets-engine.task-execution.service-pilot",
|
||||
"policy_status": "proposed",
|
||||
"registry_overrode": [],
|
||||
"registry_resource": false,
|
||||
"registry_subject": false
|
||||
},
|
||||
"provenance": {
|
||||
"evaluator": "flex-auth/local",
|
||||
"mode": "standalone",
|
||||
"policy_package": "secrets-engine.task-execution.service-pilot",
|
||||
"policy_version": "v2",
|
||||
"policy_package_digest": "sha256:fc5a8769886b72006ba298bc0799741d0f1ed327dde9e36a6c35d26be4ea0bdc",
|
||||
"registry_snapshot_digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
|
||||
"input_claim_digests": {
|
||||
"context": "sha256:908f4edd173f06b6728bde1351316f0dcb644f8c209ef6459aa3b53c1ee0bfcb"
|
||||
},
|
||||
"decision_time": "2026-10-16T09:06:33Z",
|
||||
"approval_observation": {
|
||||
"source_id": "synthetic-actual-approval-app",
|
||||
"source_revision": "actual-owner-python-source-fixture",
|
||||
"configuration_digest": "sha256:87e9190aed4ba05323551621cd3e0567357e2f41de9af356f2f8b77d57d63b2d",
|
||||
"claim_digest": "sha256:c4eefea24458257b1d10a7186729a271e8a219f1b9763294eab01eb832aaaaa2",
|
||||
"native_binding_digest": "sha256:19cfbe20e156cef1f4c0a37842c47666d2f5b2164d803d77a12346ed38a9444d",
|
||||
"observed_at": "2026-10-16T09:06:33Z",
|
||||
"not_after": "2026-10-16T09:07:33Z",
|
||||
"validated_at": "2026-10-16T09:06:33.709710196Z"
|
||||
},
|
||||
"caller": {
|
||||
"mode": "enforce",
|
||||
"principal": "system:serviceaccount:secrets-engine:secrets-engine",
|
||||
"audience": "flex-auth",
|
||||
"not_after": "2026-10-16T09:08:33Z"
|
||||
}
|
||||
},
|
||||
"signature": {
|
||||
"mode": "signed",
|
||||
"alg": "ed25519",
|
||||
"kid": "synthetic-v2",
|
||||
"value": "4gO4Cqr0fCiIP3Az-Tz8XP0qmgmxfU4S8Oz7y1vKgE7gsV7swNXcJ3hzs1wx1-H3mdoGEQz13URiq94cZO5KBA"
|
||||
},
|
||||
"caring": {
|
||||
"profile": "caring-0.4.0-rc2",
|
||||
"conformance_findings": [
|
||||
{
|
||||
"code": "CARING-DESCRIPTOR-MISSING",
|
||||
"severity": "warning",
|
||||
"message": "no CARING descriptor matched the request",
|
||||
"fields": [
|
||||
"caring_context"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"existing_producer_signature_verified":true,"independent_synthetic_public_fixture":true,"returned_record_canonical_bytes_match":true,"new_signature_implementation":false}
|
||||
|
|
@ -0,0 +1,229 @@
|
|||
{
|
||||
"id": "decision:f85ef006900157fe",
|
||||
"contract_version": "flex-auth.decision-record.v1",
|
||||
"effect": "allow",
|
||||
"reason": "exact_task_execution_matched",
|
||||
"matched_policy_version": "v2",
|
||||
"matched_rule": "exact_task_execution_matched",
|
||||
"resource": {
|
||||
"id": "catalog:synthetic",
|
||||
"type": "secret-catalog-lane",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
}
|
||||
},
|
||||
"subject": {
|
||||
"id": "secrets-engine",
|
||||
"type": "service",
|
||||
"tenant": "tenant:platform"
|
||||
},
|
||||
"binding": {
|
||||
"tenant": "tenant:platform",
|
||||
"subject": {
|
||||
"id": "secrets-engine",
|
||||
"type": "service",
|
||||
"tenant": "tenant:platform"
|
||||
},
|
||||
"action": "execute-ccr",
|
||||
"resource": {
|
||||
"id": "catalog:synthetic",
|
||||
"type": "secret-catalog-lane",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
}
|
||||
},
|
||||
"context": {
|
||||
"approval": {
|
||||
"approval_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
|
||||
"binding": {
|
||||
"action": "execute-ccr",
|
||||
"actor": "secrets-engine",
|
||||
"digest": "sha256:19cfbe20e156cef1f4c0a37842c47666d2f5b2164d803d77a12346ed38a9444d",
|
||||
"human_control": true,
|
||||
"pdp_digest": "sha256:945b3b5c014370f1a64dbca47c44a5c85124b294b6e6a11e4974c958530aa86b",
|
||||
"pdp_path": true,
|
||||
"principal": "secrets-engine",
|
||||
"purpose": "actual Python App source-only synthetic proof",
|
||||
"target": {
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
},
|
||||
"id": "catalog:synthetic",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"type": "secret-catalog-lane"
|
||||
}
|
||||
},
|
||||
"consumed": false,
|
||||
"freshness": {
|
||||
"not_after": "2026-10-16T09:07:33+00:00",
|
||||
"observed_at": "2026-10-16T09:06:33+00:00",
|
||||
"ttl_seconds": 60
|
||||
},
|
||||
"issuer": "approval-engine",
|
||||
"kind": "approval-claim",
|
||||
"reason_code": "ok",
|
||||
"schema_version": "0.1",
|
||||
"state": "valid",
|
||||
"valid_now": true,
|
||||
"validity": {
|
||||
"expires_at": "2026-10-16T09:09:33.329626+00:00",
|
||||
"not_before": "2026-10-16T09:05:33.329626+00:00"
|
||||
},
|
||||
"yields_to": "net-kingdom taxonomy request-claim schema (statute \u00a717; unassigned)"
|
||||
},
|
||||
"catalog_target": {
|
||||
"lane": "synthetic",
|
||||
"stage": "prod"
|
||||
},
|
||||
"execution_contract": {
|
||||
"backend_budget": {
|
||||
"ttl_seconds": 120,
|
||||
"uses": 12
|
||||
},
|
||||
"backend_origin": "http://127.0.0.1:18200",
|
||||
"catalog_sha256": "sha256:290e55b2258d66980f9443ba7d1436adfc77b8814bd161004d5af2ba272bc9cc",
|
||||
"ccr_id": "CCR-2099-0001",
|
||||
"ccr_immutable_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"cluster_uid": "synthetic-not-native",
|
||||
"contract_version": "SECRETS-EXEC-20261011-v1",
|
||||
"execution_actor": "service:secrets-engine",
|
||||
"execution_grant_ccr_id": "CCR-2099-0002",
|
||||
"expected_after": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"expected_before": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"grant_immutable_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"operation": "metadata-apply-ccr",
|
||||
"operation_deadline": "2026-10-16T09:08:13.606884+00:00",
|
||||
"operation_id": "cbfbced0-09d5-48c8-a1e7-a2ea4dc69153",
|
||||
"operations": [
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
],
|
||||
"source_bundle": {
|
||||
"engine_dispatcher": {
|
||||
"path": "/synthetic/engine_dispatcher.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"platform_mediator": {
|
||||
"path": "/synthetic/platform_mediator.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"policy_auth": {
|
||||
"path": "/synthetic/policy_auth.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"typed_ccr": {
|
||||
"path": "/synthetic/typed_ccr.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
}
|
||||
},
|
||||
"human_control": true,
|
||||
"purpose": "actual Python App source-only synthetic proof",
|
||||
"service_actor_binding": {
|
||||
"subject_id": "secrets-engine",
|
||||
"subject_type": "service",
|
||||
"tenant": "tenant:platform",
|
||||
"transport_principal": "system:serviceaccount:secrets-engine:secrets-engine",
|
||||
"version": "proposed-service-task-caller/v1"
|
||||
}
|
||||
},
|
||||
"request_digest": "sha256:18db34b2bad28d655d96ce62e3a0a62bf54f47aea6041f41068b404497fec001",
|
||||
"approval_binding_digest": "sha256:945b3b5c014370f1a64dbca47c44a5c85124b294b6e6a11e4974c958530aa86b",
|
||||
"submitted_request_digest": "sha256:18db34b2bad28d655d96ce62e3a0a62bf54f47aea6041f41068b404497fec001"
|
||||
},
|
||||
"lifetime": {
|
||||
"kind": "ttl",
|
||||
"ttl": "15s",
|
||||
"not_before": "2026-10-16T09:06:33Z",
|
||||
"expires_at": "2026-10-16T09:06:48Z"
|
||||
},
|
||||
"diagnostics": {
|
||||
"action": "execute-ccr",
|
||||
"matched_relationship": "",
|
||||
"policy_package": "secrets-engine.task-execution.service-pilot",
|
||||
"policy_status": "proposed",
|
||||
"registry_overrode": [],
|
||||
"registry_resource": false,
|
||||
"registry_subject": false
|
||||
},
|
||||
"provenance": {
|
||||
"evaluator": "flex-auth/local",
|
||||
"mode": "standalone",
|
||||
"policy_package": "secrets-engine.task-execution.service-pilot",
|
||||
"policy_version": "v2",
|
||||
"policy_package_digest": "sha256:fc5a8769886b72006ba298bc0799741d0f1ed327dde9e36a6c35d26be4ea0bdc",
|
||||
"registry_snapshot_digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
|
||||
"input_claim_digests": {
|
||||
"context": "sha256:908f4edd173f06b6728bde1351316f0dcb644f8c209ef6459aa3b53c1ee0bfcb"
|
||||
},
|
||||
"decision_time": "2026-10-16T09:06:33Z",
|
||||
"approval_observation": {
|
||||
"source_id": "synthetic-actual-approval-app",
|
||||
"source_revision": "actual-owner-python-source-fixture",
|
||||
"configuration_digest": "sha256:87e9190aed4ba05323551621cd3e0567357e2f41de9af356f2f8b77d57d63b2d",
|
||||
"claim_digest": "sha256:c4eefea24458257b1d10a7186729a271e8a219f1b9763294eab01eb832aaaaa2",
|
||||
"native_binding_digest": "sha256:19cfbe20e156cef1f4c0a37842c47666d2f5b2164d803d77a12346ed38a9444d",
|
||||
"observed_at": "2026-10-16T09:06:33Z",
|
||||
"not_after": "2026-10-16T09:07:33Z",
|
||||
"validated_at": "2026-10-16T09:06:33.709710196Z"
|
||||
},
|
||||
"caller": {
|
||||
"mode": "enforce",
|
||||
"principal": "system:serviceaccount:secrets-engine:secrets-engine",
|
||||
"audience": "flex-auth",
|
||||
"not_after": "2026-10-16T09:08:33Z"
|
||||
}
|
||||
},
|
||||
"signature": {
|
||||
"mode": "signed",
|
||||
"alg": "ed25519",
|
||||
"kid": "synthetic-v2",
|
||||
"value": "4gO4Cqr0fCiIP3Az-Tz8XP0qmgmxfU4S8Oz7y1vKgE7gsV7swNXcJ3hzs1wx1-H3mdoGEQz13URiq94cZO5KBA"
|
||||
},
|
||||
"caring": {
|
||||
"profile": "caring-0.4.0-rc2",
|
||||
"conformance_findings": [
|
||||
{
|
||||
"code": "CARING-DESCRIPTOR-MISSING",
|
||||
"severity": "warning",
|
||||
"message": "no CARING descriptor matched the request",
|
||||
"fields": [
|
||||
"caring_context"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"scope": "synthetic disposable fixture only; no native key admission",
|
||||
"kid": "synthetic-v2",
|
||||
"public_key": "Zs1gi5KLiOUODv6qM_rxxDzv4HKUsLh-n-CrpqPPdjM"
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ed25519"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/netkingdom/access-engine/internal/sign"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
raw, err := os.ReadFile(os.Args[1])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
trust, err := os.ReadFile(os.Args[2])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var public struct {
|
||||
KID string `json:"kid"`
|
||||
Public string `json:"public_key"`
|
||||
}
|
||||
if json.Unmarshal(trust, &public) != nil {
|
||||
panic("trust decode")
|
||||
}
|
||||
key, err := base64.RawURLEncoding.DecodeString(public.Public)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
envelope, err := sign.DecodeEnvelope(raw)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := sign.Verify(envelope, map[string]ed25519.PublicKey{public.KID: ed25519.PublicKey(key)}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
record, err := os.ReadFile(os.Args[3])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
source, err := sign.DecodeEnvelope(record)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
a, _ := sign.CanonicalBytes(envelope)
|
||||
b, _ := sign.CanonicalBytes(source)
|
||||
if !bytes.Equal(a, b) {
|
||||
panic("canonical record mismatch")
|
||||
}
|
||||
fmt.Println(`{"existing_producer_signature_verified":true,"independent_synthetic_public_fixture":true,"returned_record_canonical_bytes_match":true,"new_signature_implementation":false}`)
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"supersedes_review_caveat": "owner-source-review-r1.json remaining_proof actual Python App/Engine source fixture is now complete",
|
||||
"actual_producer_proof": "actual-python-source/receipt.json",
|
||||
"signature_proof": "actual-python-source/signature-verification.json",
|
||||
"remaining_proof": [
|
||||
"independent source review",
|
||||
"strict Secrets refreshed producer source/bundle acceptance",
|
||||
"Platform exact successor whole-stack positive and negatives",
|
||||
"owner-admitted native source/custody/key/image provenance and rollout separately"
|
||||
],
|
||||
"native_acceptance": false,
|
||||
"artifact_sha256": {
|
||||
"actual-python-source/original-approval-claim.json": "002221b16301dbc61767a926e950dad594bb3e6b6f6c1d9e038deeb56ca9dd83",
|
||||
"actual-python-source/receipt.json": "11d114aa8f8e7956fc2231de9ea91baf887c90bf7251d8f703b0881b49e23284",
|
||||
"actual-python-source/request.json": "47793f3bad156f0b50e8d9bb663c585c5fce779b87a59aac0887b4f2dfe8799f",
|
||||
"actual-python-source/response.json": "592b375208d6c2d5add685df0e789b3e0adc0794989712871a518b1a6800e1dc",
|
||||
"actual-python-source/signature-verification.json": "cedaa2294985c0d793f1ee9bf31ca34f6dd7ef304226166feec3b96820422066",
|
||||
"actual-python-source/source-dependencies.json": "0c9a5ec99aaefdf775a4510cabff3ccd75f0d35efb1b0819dd15367f8a6c3c0f",
|
||||
"actual-python-source/source-record.json": "592b375208d6c2d5add685df0e789b3e0adc0794989712871a518b1a6800e1dc",
|
||||
"actual-python-source/synthetic-public-trust.json": "08bee627543864ba29aa422cdf7c73ccffd864f9a40cd5022b0cecb948207072"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"owner": "Access Engine",
|
||||
"status": "source proposal ready for independent coordinator and cross-owner review",
|
||||
"implementation": "fixed source-authenticated Approval PIP reader + unchanged owner canonical/fact helper + typed existing PDP evaluator; no new PDP",
|
||||
"synthetic_positive": "Actual HTTP handler and production serve subprocess, real TLS TokenReview and fixed TLS Approval-source fixture; signed ALLOW, exact original context and numeric kind, published digest compatibility and response/JSONL parity",
|
||||
"negatives": [
|
||||
"redirects",
|
||||
"source duplicates",
|
||||
"source consumed",
|
||||
"source expiry",
|
||||
"stale original despite fresh provider",
|
||||
"native integer/float authority mutation",
|
||||
"invalid source media/encoding/UTF8",
|
||||
"bounded response and context deadline",
|
||||
"unsafe mounted token permissions",
|
||||
"request-selected origin/path/tenant",
|
||||
"generic/missing typed path"
|
||||
],
|
||||
"numeric_replay": "Original numeric representation retained in request and authoritative registry, unchanged Approval helper canonicalizes native act, digest-only existing PDP projection, unchanged signature Marshal; JSONL/outbox replay retain numeric signed bytes",
|
||||
"remaining_proof": [
|
||||
"independent source review",
|
||||
"actual Python App/Engine source fixture beyond current HTTP schema/helper fixture",
|
||||
"strict Secrets refreshed producer source/bundle acceptance",
|
||||
"Platform exact successor whole-stack positive and negatives",
|
||||
"owner-admitted native source/custody/key/image provenance and rollout separately"
|
||||
],
|
||||
"native_acceptance": false,
|
||||
"runtime_changes": false,
|
||||
"policy_v1_unchanged": true
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
"""Disposable synthetic proof: actual Approval App HTTPS -> actual Access serve.
|
||||
No native config, credential environment, approval or backend effect is used.
|
||||
"""
|
||||
import base64, hashlib, http.server, io, json, os, pathlib, socket, ssl, subprocess, sys, tempfile, threading, time
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from wsgiref.simple_server import make_server, WSGIRequestHandler
|
||||
from cryptography import x509
|
||||
from cryptography.x509.oid import NameOID
|
||||
from cryptography.hazmat.primitives import hashes, serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||
sys.path.insert(0, '/home/worsch/approval-engine')
|
||||
sys.path.insert(0, '/home/worsch/secrets-engine/src')
|
||||
from approval_engine.api import App
|
||||
from approval_engine.auth import Identity, StaticTokenAuthenticator
|
||||
from approval_engine.store import Engine
|
||||
from secrets_engine.authorization import request_digest, approval_binding_digest
|
||||
from urllib.request import Request, urlopen
|
||||
from urllib.error import HTTPError
|
||||
|
||||
OUT=pathlib.Path(sys.argv[1]);OUT.mkdir(exist_ok=True)
|
||||
def digest(raw):return 'sha256:'+hashlib.sha256(raw).hexdigest()
|
||||
def write(path,raw,mode=0o600):path.write_bytes(raw);path.chmod(mode)
|
||||
def identity(subject,kind,scopes):return Identity(subject=subject,issuer='synthetic-test-only',audiences=('approval-engine',),principal_type=kind,tenant='tenant:platform',roles=frozenset(),scopes=frozenset(scopes),assurance={'level':'synthetic'},evidence_ref='synthetic-test-only',tenant_source='directory')
|
||||
class Quiet(WSGIRequestHandler):
|
||||
def log_message(self,*args):pass
|
||||
class Review(http.server.BaseHTTPRequestHandler):
|
||||
def do_POST(self):
|
||||
raw=self.rfile.read(int(self.headers['Content-Length']));body=json.loads(raw)
|
||||
assert self.path=='/apis/authentication.k8s.io/v1/tokenreviews'
|
||||
assert self.headers['Authorization']=='Bearer synthetic-reviewer'
|
||||
assert body['spec']['audiences']==['flex-auth','access-engine']
|
||||
self.send_response(200);self.send_header('Content-Type','application/json');self.end_headers();self.wfile.write(json.dumps({'status':{'authenticated':True,'audiences':['flex-auth'],'user':{'username':'system:serviceaccount:secrets-engine:secrets-engine'}}}).encode())
|
||||
def log_message(self,*args):pass
|
||||
with tempfile.TemporaryDirectory(prefix='access-actual-python-source-') as folder:
|
||||
root=pathlib.Path(folder);now=datetime.now(timezone.utc)
|
||||
key=rsa.generate_private_key(public_exponent=65537,key_size=2048);name=x509.Name([x509.NameAttribute(NameOID.COMMON_NAME,'localhost')]);cert=(x509.CertificateBuilder().subject_name(name).issuer_name(name).public_key(key.public_key()).serial_number(x509.random_serial_number()).not_valid_before(now-timedelta(minutes=1)).not_valid_after(now+timedelta(hours=1)).add_extension(x509.SubjectAlternativeName([x509.DNSName('localhost')]),critical=False).sign(key,hashes.SHA256()))
|
||||
ca=root/'ca.pem';private=root/'tls-key.pem';write(ca,cert.public_bytes(serialization.Encoding.PEM));write(private,key.private_bytes(serialization.Encoding.PEM,serialization.PrivateFormat.PKCS8,serialization.NoEncryption()))
|
||||
tls=ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER);tls.load_cert_chain(ca,private)
|
||||
ctx=ssl.create_default_context(cafile=str(ca))
|
||||
def start(server):server.socket=tls.wrap_socket(server.socket,server_side=True);threading.Thread(target=server.serve_forever,daemon=True).start();return 'https://localhost:'+str(server.server_port)
|
||||
review=http.server.HTTPServer(('127.0.0.1',0),Review);review_origin=start(review)
|
||||
engine=Engine(root/'approval.sqlite3',freshness_ttl=120)
|
||||
auth=StaticTokenAuthenticator({'synthetic-creator':identity('secrets-engine','service',{'approval:create'}),'synthetic-human':identity('synthetic-human','human',{'approval:approve'}),'synthetic-reader':identity('synthetic-access-reader','service',{'approval:read'})})
|
||||
app=App(engine,auth)
|
||||
source=make_server('127.0.0.1',0,app,handler_class=Quiet);origin=start(source)
|
||||
def source_call(method,path,body,token):
|
||||
request=Request(origin+path,data=json.dumps(body).encode() if body is not None else None,method=method,headers={'Authorization':'Bearer '+token,'Content-Type':'application/json'})
|
||||
with urlopen(request,context=ctx,timeout=3) as response:return response.status,json.load(response)
|
||||
# Reuse existing owner interoperability contract generator; it has synthetic metadata only.
|
||||
generated=subprocess.check_output([sys.executable,'/tmp/access-trusted-b2-b3-r2/tools/service_task_execution_fixture.py'],env={'PATH':os.defpath})
|
||||
request=json.loads(generated)['request'];request['subject']['tenant']='tenant:platform';request['resource']['tenant']='tenant:platform';request['context']['purpose']='actual Python App source-only synthetic proof';del request['context']['approval'];request['context']['execution_contract']['backend_budget']['ttl_seconds']=30;request['context']['execution_contract']['operation_deadline']=(now+timedelta(seconds=60)).replace(microsecond=0).isoformat()
|
||||
native={'action':request['action'],'actor':'secrets-engine','principal':'secrets-engine','purpose':request['context']['purpose'],'target':request['resource']}
|
||||
aid='aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee'
|
||||
status,created=source_call('POST','/v1/approvals',{'id':aid,'binding':native,'validity':{'not_before':(now-timedelta(minutes=1)).isoformat(),'expires_at':(now+timedelta(minutes=3)).isoformat()},'required_count':1,'pdp_digest':approval_binding_digest(request),'pdp_path':True,'human_control':True},'synthetic-creator');assert status==201
|
||||
status,_=source_call('POST',f'/v1/approvals/{aid}/entries',{},'synthetic-human');assert status==200
|
||||
status,claim=source_call('GET',f'/v1/approvals/{aid}/claim',None,'synthetic-reader');assert status==200 and claim['valid_now'] is True and claim['binding']['human_control'] is True
|
||||
request['context']['approval']=claim
|
||||
seed=root/'seed';write(seed,base64.urlsafe_b64encode(bytes([19])*32).rstrip(b'='),0o440)
|
||||
reviewer_token=root/'review-token';write(reviewer_token,b'synthetic-reviewer',0o440)
|
||||
reader_token=root/'reader-token';write(reader_token,b'synthetic-reader',0o440)
|
||||
registry=root/'registry.json';write(registry,b'{}')
|
||||
config=root/'source.json';write(config,json.dumps({'source_id':'synthetic-actual-approval-app','source_revision':'actual-owner-python-source-fixture','origin':origin,'store_tenant':'tenant:platform','ca_file':str(ca),'token_file':str(reader_token)}).encode())
|
||||
listener=socket.socket();listener.bind(('127.0.0.1',0));port=listener.getsockname()[1];listener.close()
|
||||
record=root/'record.jsonl';url=f'http://127.0.0.1:{port}'
|
||||
command=['/tmp/netkingdom-access-trusted-r2','serve','--addr',f'127.0.0.1:{port}','--registry',str(registry),'--policy','/tmp/access-trusted-b2-b3-r2/examples/secrets-engine-service-task-execution-v2/policy_package.md','--log',str(record),'--caller-auth-mode','enforce','--caller-audience','flex-auth','--caller-kubernetes-url',review_origin,'--caller-reviewer-token-file',str(reviewer_token),'--caller-ca-file',str(ca),'--caller-binding','secrets-engine=system:serviceaccount:secrets-engine:secrets-engine','--envelope-signing-key-file',str(seed),'--envelope-signing-kid','synthetic-v2','--approval-source-file',str(config)]
|
||||
child=subprocess.Popen(command,env={},stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL)
|
||||
try:
|
||||
for _ in range(100):
|
||||
try:
|
||||
with urlopen(url+'/healthz',timeout=.2):break
|
||||
except Exception:time.sleep(.02)
|
||||
jwt='synthetic.'+base64.urlsafe_b64encode(json.dumps({'exp':int((now+timedelta(minutes=2)).timestamp())}).encode()).decode().rstrip('=')+'.synthetic'
|
||||
def check(value):
|
||||
req=Request(url+'/v1/check',data=json.dumps(value).encode(),headers={'Authorization':'Bearer '+jwt,'Content-Type':'application/json'})
|
||||
try:
|
||||
with urlopen(req,timeout=5) as response:return response.status,response.read()
|
||||
except HTTPError as error:return error.code,error.read()
|
||||
status,raw=check(request);assert status==200,(status,raw)
|
||||
response=json.loads(raw);assert response['effect']=='allow' and response['signature']['mode']=='signed'
|
||||
assert response['lifetime']['expires_at']==request['context']['execution_contract']['operation_deadline'].replace('+00:00','Z');assert response['binding']['context']==request['context'];assert response['binding']['submitted_request_digest']==request_digest(request);assert response['binding']['approval_binding_digest']==approval_binding_digest(request)
|
||||
assert response['provenance']['approval_observation']['source_id']=='synthetic-actual-approval-app'
|
||||
saved=record.read_bytes();assert json.loads(saved)==response
|
||||
# Actual producer state transition is fetched anew and cannot be rescued by carried claim.
|
||||
engine.revoke(aid)
|
||||
refused,_=check(request);assert refused!=200 and record.read_bytes()==saved
|
||||
for name,value in [('request.json',request),('response.json',response),('source-record.json',json.loads(saved)),('original-approval-claim.json',claim)]:write(OUT/name,(json.dumps(value,indent=2)+'\n').encode(),0o644)
|
||||
receipt={'scope':'disposable synthetic only','actual_source':'Approval App over TLS with authenticated create, configured synthetic human entry, read; actual SQLite engine','actual_access':'production serve binary from B2/B3 R2 temporal successor','allow':True,'backend_ttl_seconds':30,'operation_authority_seconds':60,'explicit_approval_freshness_seconds':120,'decision_expiry_equals_exact_operation_deadline':True,'original_context_unchanged':True,'published_digest_match':True,'returned_source_record_match':True,'actual_source_revoke_refused':True,'no_record_after_refusal':True,'native_admission':False,'files_sha256':{p.name:digest(p.read_bytes()) for p in OUT.iterdir() if p.suffix=='.json'}}
|
||||
write(OUT/'receipt.json',(json.dumps(receipt,indent=2)+'\n').encode(),0o644);print(json.dumps(receipt,indent=2))
|
||||
finally:
|
||||
child.terminate();child.wait(timeout=5);source.shutdown();review.shutdown();engine.close()
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"approval_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
|
||||
"binding": {
|
||||
"action": "execute-ccr",
|
||||
"actor": "secrets-engine",
|
||||
"digest": "sha256:19cfbe20e156cef1f4c0a37842c47666d2f5b2164d803d77a12346ed38a9444d",
|
||||
"human_control": true,
|
||||
"pdp_digest": "sha256:1314ecedf5f8607a41ac4b5f951a4f47460ff4a6fecff70b057698688a5e71e4",
|
||||
"pdp_path": true,
|
||||
"principal": "secrets-engine",
|
||||
"purpose": "actual Python App source-only synthetic proof",
|
||||
"target": {
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
},
|
||||
"id": "catalog:synthetic",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"type": "secret-catalog-lane"
|
||||
}
|
||||
},
|
||||
"consumed": false,
|
||||
"freshness": {
|
||||
"not_after": "2026-10-16T14:39:10+00:00",
|
||||
"observed_at": "2026-10-16T14:37:10+00:00",
|
||||
"ttl_seconds": 120
|
||||
},
|
||||
"issuer": "approval-engine",
|
||||
"kind": "approval-claim",
|
||||
"reason_code": "ok",
|
||||
"schema_version": "0.1",
|
||||
"state": "valid",
|
||||
"valid_now": true,
|
||||
"validity": {
|
||||
"expires_at": "2026-10-16T14:40:10.168539+00:00",
|
||||
"not_before": "2026-10-16T14:36:10.168539+00:00"
|
||||
},
|
||||
"yields_to": "net-kingdom taxonomy request-claim schema (statute \u00a717; unassigned)"
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"scope": "disposable synthetic only",
|
||||
"actual_source": "Approval App over TLS with authenticated create, configured synthetic human entry, read; actual SQLite engine",
|
||||
"actual_access": "production serve binary from B2/B3 R2 temporal successor",
|
||||
"allow": true,
|
||||
"backend_ttl_seconds": 30,
|
||||
"operation_authority_seconds": 60,
|
||||
"explicit_approval_freshness_seconds": 120,
|
||||
"decision_expiry_equals_exact_operation_deadline": true,
|
||||
"original_context_unchanged": true,
|
||||
"published_digest_match": true,
|
||||
"returned_source_record_match": true,
|
||||
"actual_source_revoke_refused": true,
|
||||
"no_record_after_refusal": true,
|
||||
"native_admission": false,
|
||||
"files_sha256": {
|
||||
"source-record.json": "sha256:5fab76b026ac330233517b4de85cd9aeda096de6a2b118300cffd177652ad38e",
|
||||
"response.json": "sha256:5fab76b026ac330233517b4de85cd9aeda096de6a2b118300cffd177652ad38e",
|
||||
"original-approval-claim.json": "sha256:d03abc6f2278cb87e0c7f36a4e5342902bd3f17c6c4e19862c2e7784564bea14",
|
||||
"request.json": "sha256:fc04f36cf1e0ef03995336665c411de62044194e73ee953ceebc7f615cc1de5d"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
{
|
||||
"tenant": "tenant:platform",
|
||||
"subject": {
|
||||
"id": "secrets-engine",
|
||||
"type": "service",
|
||||
"tenant": "tenant:platform"
|
||||
},
|
||||
"action": "execute-ccr",
|
||||
"resource": {
|
||||
"id": "catalog:synthetic",
|
||||
"type": "secret-catalog-lane",
|
||||
"system": "secrets-engine",
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
},
|
||||
"tenant": "tenant:platform"
|
||||
},
|
||||
"context": {
|
||||
"execution_contract": {
|
||||
"backend_budget": {
|
||||
"ttl_seconds": 30,
|
||||
"uses": 12
|
||||
},
|
||||
"backend_origin": "http://127.0.0.1:18200",
|
||||
"catalog_sha256": "sha256:290e55b2258d66980f9443ba7d1436adfc77b8814bd161004d5af2ba272bc9cc",
|
||||
"ccr_id": "CCR-2099-0001",
|
||||
"ccr_immutable_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"cluster_uid": "synthetic-not-native",
|
||||
"contract_version": "SECRETS-EXEC-20261011-v1",
|
||||
"execution_actor": "service:secrets-engine",
|
||||
"execution_grant_ccr_id": "CCR-2099-0002",
|
||||
"expected_after": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"expected_before": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"grant_immutable_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"operation": "metadata-apply-ccr",
|
||||
"operation_deadline": "2026-10-16T14:38:10+00:00",
|
||||
"operation_id": "cbfbced0-09d5-48c8-a1e7-a2ea4dc69153",
|
||||
"operations": [
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
],
|
||||
"source_bundle": {
|
||||
"engine_dispatcher": {
|
||||
"path": "/synthetic/engine_dispatcher.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"platform_mediator": {
|
||||
"path": "/synthetic/platform_mediator.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"policy_auth": {
|
||||
"path": "/synthetic/policy_auth.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"typed_ccr": {
|
||||
"path": "/synthetic/typed_ccr.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
}
|
||||
},
|
||||
"catalog_target": {
|
||||
"lane": "synthetic",
|
||||
"stage": "prod"
|
||||
},
|
||||
"human_control": true,
|
||||
"service_actor_binding": {
|
||||
"version": "proposed-service-task-caller/v1",
|
||||
"transport_principal": "system:serviceaccount:secrets-engine:secrets-engine",
|
||||
"subject_id": "secrets-engine",
|
||||
"subject_type": "service",
|
||||
"tenant": "tenant:platform"
|
||||
},
|
||||
"purpose": "actual Python App source-only synthetic proof",
|
||||
"approval": {
|
||||
"approval_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
|
||||
"binding": {
|
||||
"action": "execute-ccr",
|
||||
"actor": "secrets-engine",
|
||||
"digest": "sha256:19cfbe20e156cef1f4c0a37842c47666d2f5b2164d803d77a12346ed38a9444d",
|
||||
"human_control": true,
|
||||
"pdp_digest": "sha256:1314ecedf5f8607a41ac4b5f951a4f47460ff4a6fecff70b057698688a5e71e4",
|
||||
"pdp_path": true,
|
||||
"principal": "secrets-engine",
|
||||
"purpose": "actual Python App source-only synthetic proof",
|
||||
"target": {
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
},
|
||||
"id": "catalog:synthetic",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"type": "secret-catalog-lane"
|
||||
}
|
||||
},
|
||||
"consumed": false,
|
||||
"freshness": {
|
||||
"not_after": "2026-10-16T14:39:10+00:00",
|
||||
"observed_at": "2026-10-16T14:37:10+00:00",
|
||||
"ttl_seconds": 120
|
||||
},
|
||||
"issuer": "approval-engine",
|
||||
"kind": "approval-claim",
|
||||
"reason_code": "ok",
|
||||
"schema_version": "0.1",
|
||||
"state": "valid",
|
||||
"valid_now": true,
|
||||
"validity": {
|
||||
"expires_at": "2026-10-16T14:40:10.168539+00:00",
|
||||
"not_before": "2026-10-16T14:36:10.168539+00:00"
|
||||
},
|
||||
"yields_to": "net-kingdom taxonomy request-claim schema (statute \u00a717; unassigned)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,229 @@
|
|||
{
|
||||
"id": "decision:345172e88988026a",
|
||||
"contract_version": "flex-auth.decision-record.v1",
|
||||
"effect": "allow",
|
||||
"reason": "exact_task_execution_matched",
|
||||
"matched_policy_version": "v2",
|
||||
"matched_rule": "exact_task_execution_matched",
|
||||
"resource": {
|
||||
"id": "catalog:synthetic",
|
||||
"type": "secret-catalog-lane",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
}
|
||||
},
|
||||
"subject": {
|
||||
"id": "secrets-engine",
|
||||
"type": "service",
|
||||
"tenant": "tenant:platform"
|
||||
},
|
||||
"binding": {
|
||||
"tenant": "tenant:platform",
|
||||
"subject": {
|
||||
"id": "secrets-engine",
|
||||
"type": "service",
|
||||
"tenant": "tenant:platform"
|
||||
},
|
||||
"action": "execute-ccr",
|
||||
"resource": {
|
||||
"id": "catalog:synthetic",
|
||||
"type": "secret-catalog-lane",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
}
|
||||
},
|
||||
"context": {
|
||||
"approval": {
|
||||
"approval_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
|
||||
"binding": {
|
||||
"action": "execute-ccr",
|
||||
"actor": "secrets-engine",
|
||||
"digest": "sha256:19cfbe20e156cef1f4c0a37842c47666d2f5b2164d803d77a12346ed38a9444d",
|
||||
"human_control": true,
|
||||
"pdp_digest": "sha256:1314ecedf5f8607a41ac4b5f951a4f47460ff4a6fecff70b057698688a5e71e4",
|
||||
"pdp_path": true,
|
||||
"principal": "secrets-engine",
|
||||
"purpose": "actual Python App source-only synthetic proof",
|
||||
"target": {
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
},
|
||||
"id": "catalog:synthetic",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"type": "secret-catalog-lane"
|
||||
}
|
||||
},
|
||||
"consumed": false,
|
||||
"freshness": {
|
||||
"not_after": "2026-10-16T14:39:10+00:00",
|
||||
"observed_at": "2026-10-16T14:37:10+00:00",
|
||||
"ttl_seconds": 120
|
||||
},
|
||||
"issuer": "approval-engine",
|
||||
"kind": "approval-claim",
|
||||
"reason_code": "ok",
|
||||
"schema_version": "0.1",
|
||||
"state": "valid",
|
||||
"valid_now": true,
|
||||
"validity": {
|
||||
"expires_at": "2026-10-16T14:40:10.168539+00:00",
|
||||
"not_before": "2026-10-16T14:36:10.168539+00:00"
|
||||
},
|
||||
"yields_to": "net-kingdom taxonomy request-claim schema (statute \u00a717; unassigned)"
|
||||
},
|
||||
"catalog_target": {
|
||||
"lane": "synthetic",
|
||||
"stage": "prod"
|
||||
},
|
||||
"execution_contract": {
|
||||
"backend_budget": {
|
||||
"ttl_seconds": 30,
|
||||
"uses": 12
|
||||
},
|
||||
"backend_origin": "http://127.0.0.1:18200",
|
||||
"catalog_sha256": "sha256:290e55b2258d66980f9443ba7d1436adfc77b8814bd161004d5af2ba272bc9cc",
|
||||
"ccr_id": "CCR-2099-0001",
|
||||
"ccr_immutable_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"cluster_uid": "synthetic-not-native",
|
||||
"contract_version": "SECRETS-EXEC-20261011-v1",
|
||||
"execution_actor": "service:secrets-engine",
|
||||
"execution_grant_ccr_id": "CCR-2099-0002",
|
||||
"expected_after": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"expected_before": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"grant_immutable_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"operation": "metadata-apply-ccr",
|
||||
"operation_deadline": "2026-10-16T14:38:10+00:00",
|
||||
"operation_id": "cbfbced0-09d5-48c8-a1e7-a2ea4dc69153",
|
||||
"operations": [
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
],
|
||||
"source_bundle": {
|
||||
"engine_dispatcher": {
|
||||
"path": "/synthetic/engine_dispatcher.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"platform_mediator": {
|
||||
"path": "/synthetic/platform_mediator.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"policy_auth": {
|
||||
"path": "/synthetic/policy_auth.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"typed_ccr": {
|
||||
"path": "/synthetic/typed_ccr.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
}
|
||||
},
|
||||
"human_control": true,
|
||||
"purpose": "actual Python App source-only synthetic proof",
|
||||
"service_actor_binding": {
|
||||
"subject_id": "secrets-engine",
|
||||
"subject_type": "service",
|
||||
"tenant": "tenant:platform",
|
||||
"transport_principal": "system:serviceaccount:secrets-engine:secrets-engine",
|
||||
"version": "proposed-service-task-caller/v1"
|
||||
}
|
||||
},
|
||||
"request_digest": "sha256:5de47c87ba31a96c51cffd75e3a1236a830745c9bf2087d5a44b640b40c11540",
|
||||
"approval_binding_digest": "sha256:1314ecedf5f8607a41ac4b5f951a4f47460ff4a6fecff70b057698688a5e71e4",
|
||||
"submitted_request_digest": "sha256:5de47c87ba31a96c51cffd75e3a1236a830745c9bf2087d5a44b640b40c11540"
|
||||
},
|
||||
"lifetime": {
|
||||
"kind": "ttl",
|
||||
"ttl": "59.254796424s",
|
||||
"not_before": "2026-10-16T14:37:10.745203576Z",
|
||||
"expires_at": "2026-10-16T14:38:10Z"
|
||||
},
|
||||
"diagnostics": {
|
||||
"action": "execute-ccr",
|
||||
"matched_relationship": "",
|
||||
"policy_package": "secrets-engine.task-execution.service-pilot",
|
||||
"policy_status": "proposed",
|
||||
"registry_overrode": [],
|
||||
"registry_resource": false,
|
||||
"registry_subject": false
|
||||
},
|
||||
"provenance": {
|
||||
"evaluator": "flex-auth/local",
|
||||
"mode": "standalone",
|
||||
"policy_package": "secrets-engine.task-execution.service-pilot",
|
||||
"policy_version": "v2",
|
||||
"policy_package_digest": "sha256:de5683e5a34161b9349b10cd8e4abef704e0136e3b14b97719fcd7a79850fc4d",
|
||||
"registry_snapshot_digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
|
||||
"input_claim_digests": {
|
||||
"context": "sha256:1000c59c0b5765bc2de159a42c0cfa861ce840547e87edb5cadd8de20f177a31"
|
||||
},
|
||||
"decision_time": "2026-10-16T14:37:10Z",
|
||||
"approval_observation": {
|
||||
"source_id": "synthetic-actual-approval-app",
|
||||
"source_revision": "actual-owner-python-source-fixture",
|
||||
"configuration_digest": "sha256:b646af61ef4d13a89c82a267d93b38eab6bcfc3ba0314550577dd883bdd221a2",
|
||||
"claim_digest": "sha256:dfeec32f189bc8ed5500bc1f7a53758183cd889ee9472dc8ee5d506dd5c67393",
|
||||
"native_binding_digest": "sha256:19cfbe20e156cef1f4c0a37842c47666d2f5b2164d803d77a12346ed38a9444d",
|
||||
"observed_at": "2026-10-16T14:37:10Z",
|
||||
"not_after": "2026-10-16T14:39:10Z",
|
||||
"validated_at": "2026-10-16T14:37:10.733320979Z"
|
||||
},
|
||||
"caller": {
|
||||
"mode": "enforce",
|
||||
"principal": "system:serviceaccount:secrets-engine:secrets-engine",
|
||||
"audience": "flex-auth",
|
||||
"not_after": "2026-10-16T14:39:10Z"
|
||||
}
|
||||
},
|
||||
"signature": {
|
||||
"mode": "signed",
|
||||
"alg": "ed25519",
|
||||
"kid": "synthetic-v2",
|
||||
"value": "XP7oAYq5QDFThW8NkQunirFEcCmOwqkxeJiaQWbJGdi--x2XEVOtJH_mZmAQGeTXmcZGWS6WNtNVltgD2NxVDA"
|
||||
},
|
||||
"caring": {
|
||||
"profile": "caring-0.4.0-rc2",
|
||||
"conformance_findings": [
|
||||
{
|
||||
"code": "CARING-DESCRIPTOR-MISSING",
|
||||
"severity": "warning",
|
||||
"message": "no CARING descriptor matched the request",
|
||||
"fields": [
|
||||
"caring_context"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"existing_producer_signature_verified":true,"independent_synthetic_public_fixture":true,"returned_record_canonical_bytes_match":true,"new_signature_implementation":false}
|
||||
|
|
@ -0,0 +1,229 @@
|
|||
{
|
||||
"id": "decision:345172e88988026a",
|
||||
"contract_version": "flex-auth.decision-record.v1",
|
||||
"effect": "allow",
|
||||
"reason": "exact_task_execution_matched",
|
||||
"matched_policy_version": "v2",
|
||||
"matched_rule": "exact_task_execution_matched",
|
||||
"resource": {
|
||||
"id": "catalog:synthetic",
|
||||
"type": "secret-catalog-lane",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
}
|
||||
},
|
||||
"subject": {
|
||||
"id": "secrets-engine",
|
||||
"type": "service",
|
||||
"tenant": "tenant:platform"
|
||||
},
|
||||
"binding": {
|
||||
"tenant": "tenant:platform",
|
||||
"subject": {
|
||||
"id": "secrets-engine",
|
||||
"type": "service",
|
||||
"tenant": "tenant:platform"
|
||||
},
|
||||
"action": "execute-ccr",
|
||||
"resource": {
|
||||
"id": "catalog:synthetic",
|
||||
"type": "secret-catalog-lane",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
}
|
||||
},
|
||||
"context": {
|
||||
"approval": {
|
||||
"approval_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
|
||||
"binding": {
|
||||
"action": "execute-ccr",
|
||||
"actor": "secrets-engine",
|
||||
"digest": "sha256:19cfbe20e156cef1f4c0a37842c47666d2f5b2164d803d77a12346ed38a9444d",
|
||||
"human_control": true,
|
||||
"pdp_digest": "sha256:1314ecedf5f8607a41ac4b5f951a4f47460ff4a6fecff70b057698688a5e71e4",
|
||||
"pdp_path": true,
|
||||
"principal": "secrets-engine",
|
||||
"purpose": "actual Python App source-only synthetic proof",
|
||||
"target": {
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
},
|
||||
"id": "catalog:synthetic",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"type": "secret-catalog-lane"
|
||||
}
|
||||
},
|
||||
"consumed": false,
|
||||
"freshness": {
|
||||
"not_after": "2026-10-16T14:39:10+00:00",
|
||||
"observed_at": "2026-10-16T14:37:10+00:00",
|
||||
"ttl_seconds": 120
|
||||
},
|
||||
"issuer": "approval-engine",
|
||||
"kind": "approval-claim",
|
||||
"reason_code": "ok",
|
||||
"schema_version": "0.1",
|
||||
"state": "valid",
|
||||
"valid_now": true,
|
||||
"validity": {
|
||||
"expires_at": "2026-10-16T14:40:10.168539+00:00",
|
||||
"not_before": "2026-10-16T14:36:10.168539+00:00"
|
||||
},
|
||||
"yields_to": "net-kingdom taxonomy request-claim schema (statute \u00a717; unassigned)"
|
||||
},
|
||||
"catalog_target": {
|
||||
"lane": "synthetic",
|
||||
"stage": "prod"
|
||||
},
|
||||
"execution_contract": {
|
||||
"backend_budget": {
|
||||
"ttl_seconds": 30,
|
||||
"uses": 12
|
||||
},
|
||||
"backend_origin": "http://127.0.0.1:18200",
|
||||
"catalog_sha256": "sha256:290e55b2258d66980f9443ba7d1436adfc77b8814bd161004d5af2ba272bc9cc",
|
||||
"ccr_id": "CCR-2099-0001",
|
||||
"ccr_immutable_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"cluster_uid": "synthetic-not-native",
|
||||
"contract_version": "SECRETS-EXEC-20261011-v1",
|
||||
"execution_actor": "service:secrets-engine",
|
||||
"execution_grant_ccr_id": "CCR-2099-0002",
|
||||
"expected_after": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"expected_before": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"grant_immutable_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"operation": "metadata-apply-ccr",
|
||||
"operation_deadline": "2026-10-16T14:38:10+00:00",
|
||||
"operation_id": "cbfbced0-09d5-48c8-a1e7-a2ea4dc69153",
|
||||
"operations": [
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
],
|
||||
"source_bundle": {
|
||||
"engine_dispatcher": {
|
||||
"path": "/synthetic/engine_dispatcher.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"platform_mediator": {
|
||||
"path": "/synthetic/platform_mediator.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"policy_auth": {
|
||||
"path": "/synthetic/policy_auth.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"typed_ccr": {
|
||||
"path": "/synthetic/typed_ccr.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
}
|
||||
},
|
||||
"human_control": true,
|
||||
"purpose": "actual Python App source-only synthetic proof",
|
||||
"service_actor_binding": {
|
||||
"subject_id": "secrets-engine",
|
||||
"subject_type": "service",
|
||||
"tenant": "tenant:platform",
|
||||
"transport_principal": "system:serviceaccount:secrets-engine:secrets-engine",
|
||||
"version": "proposed-service-task-caller/v1"
|
||||
}
|
||||
},
|
||||
"request_digest": "sha256:5de47c87ba31a96c51cffd75e3a1236a830745c9bf2087d5a44b640b40c11540",
|
||||
"approval_binding_digest": "sha256:1314ecedf5f8607a41ac4b5f951a4f47460ff4a6fecff70b057698688a5e71e4",
|
||||
"submitted_request_digest": "sha256:5de47c87ba31a96c51cffd75e3a1236a830745c9bf2087d5a44b640b40c11540"
|
||||
},
|
||||
"lifetime": {
|
||||
"kind": "ttl",
|
||||
"ttl": "59.254796424s",
|
||||
"not_before": "2026-10-16T14:37:10.745203576Z",
|
||||
"expires_at": "2026-10-16T14:38:10Z"
|
||||
},
|
||||
"diagnostics": {
|
||||
"action": "execute-ccr",
|
||||
"matched_relationship": "",
|
||||
"policy_package": "secrets-engine.task-execution.service-pilot",
|
||||
"policy_status": "proposed",
|
||||
"registry_overrode": [],
|
||||
"registry_resource": false,
|
||||
"registry_subject": false
|
||||
},
|
||||
"provenance": {
|
||||
"evaluator": "flex-auth/local",
|
||||
"mode": "standalone",
|
||||
"policy_package": "secrets-engine.task-execution.service-pilot",
|
||||
"policy_version": "v2",
|
||||
"policy_package_digest": "sha256:de5683e5a34161b9349b10cd8e4abef704e0136e3b14b97719fcd7a79850fc4d",
|
||||
"registry_snapshot_digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
|
||||
"input_claim_digests": {
|
||||
"context": "sha256:1000c59c0b5765bc2de159a42c0cfa861ce840547e87edb5cadd8de20f177a31"
|
||||
},
|
||||
"decision_time": "2026-10-16T14:37:10Z",
|
||||
"approval_observation": {
|
||||
"source_id": "synthetic-actual-approval-app",
|
||||
"source_revision": "actual-owner-python-source-fixture",
|
||||
"configuration_digest": "sha256:b646af61ef4d13a89c82a267d93b38eab6bcfc3ba0314550577dd883bdd221a2",
|
||||
"claim_digest": "sha256:dfeec32f189bc8ed5500bc1f7a53758183cd889ee9472dc8ee5d506dd5c67393",
|
||||
"native_binding_digest": "sha256:19cfbe20e156cef1f4c0a37842c47666d2f5b2164d803d77a12346ed38a9444d",
|
||||
"observed_at": "2026-10-16T14:37:10Z",
|
||||
"not_after": "2026-10-16T14:39:10Z",
|
||||
"validated_at": "2026-10-16T14:37:10.733320979Z"
|
||||
},
|
||||
"caller": {
|
||||
"mode": "enforce",
|
||||
"principal": "system:serviceaccount:secrets-engine:secrets-engine",
|
||||
"audience": "flex-auth",
|
||||
"not_after": "2026-10-16T14:39:10Z"
|
||||
}
|
||||
},
|
||||
"signature": {
|
||||
"mode": "signed",
|
||||
"alg": "ed25519",
|
||||
"kid": "synthetic-v2",
|
||||
"value": "XP7oAYq5QDFThW8NkQunirFEcCmOwqkxeJiaQWbJGdi--x2XEVOtJH_mZmAQGeTXmcZGWS6WNtNVltgD2NxVDA"
|
||||
},
|
||||
"caring": {
|
||||
"profile": "caring-0.4.0-rc2",
|
||||
"conformance_findings": [
|
||||
{
|
||||
"code": "CARING-DESCRIPTOR-MISSING",
|
||||
"severity": "warning",
|
||||
"message": "no CARING descriptor matched the request",
|
||||
"fields": [
|
||||
"caring_context"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"scope": "synthetic disposable fixture only; no native key admission",
|
||||
"kid": "synthetic-v2",
|
||||
"public_key": "Zs1gi5KLiOUODv6qM_rxxDzv4HKUsLh-n-CrpqPPdjM"
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"owner": "Access Engine",
|
||||
"status": "source proposal for independent coordinator review",
|
||||
"supersedes": "R1 temporal behavior only; all R1 artifacts preserved",
|
||||
"contradiction": "15s decision expiry and default Approval freshness30 cannot bound backendmin30+cleanupreserve5 under whole-operation authority",
|
||||
"authoritative_facts": {
|
||||
"Secrets task-scoped-openbao-execution-contract.md": "task TTL bounded by decision/approval/operation; min30; reserve and max120",
|
||||
"Secrets execution_contract.require_execution_deadline": "operationdeadline<=served decision/approval bound",
|
||||
"Platform task_execution_native_fixture.materialize_grant": "remaining>=declaredTTL+5 before effects",
|
||||
"Platform owner recommendation": "conservative source maximum120, backend30/deadline60, explicit Approval freshness120"
|
||||
},
|
||||
"source_correction": [
|
||||
"source policy120 is hard ceiling, not blanket ALLOW expiry",
|
||||
"exact immutable operationdeadline is actual signed expiry, retaining fractional timestamp",
|
||||
"entire operation fits original/fresh freshness+validity and caller expiry",
|
||||
"remaining>=declaredbackendTTL+5 after I/O and final evaluation",
|
||||
"max120 and structurallyinteger30..120 enforced; structurallyallowed120 refuses ifcannotfitreserve",
|
||||
"strict consumer/native checks unchanged"
|
||||
],
|
||||
"actual_proof": "actual Approval App TLS -> production Access serve ALLOW with backend30/deadline60/explicitfresh120, unchanged context/digests/record; revoke refuses",
|
||||
"negative_tests": [
|
||||
"old15s conflict",
|
||||
"below35s minimum by1ns",
|
||||
"elapsed setup consumes lifetime",
|
||||
"expired operation",
|
||||
"above120hardcap by1ns",
|
||||
"attemptedpolicycap121",
|
||||
"shorter original/fresh authority",
|
||||
"backend120 cannotfit",
|
||||
"noninteger structural TTL",
|
||||
"HTTPsource live but shorterfreshness thanoperation"
|
||||
],
|
||||
"remaining": [
|
||||
"independent source and cross-owner successor integration review",
|
||||
"Platform absolute per-call elapsed deadline/read/close and cleanup reserve proof; inactivity timeout alone is insufficient",
|
||||
"separately owner-admitted runtime freshness/trust/custody/image rollout"
|
||||
],
|
||||
"native_admission": false
|
||||
}
|
||||
|
|
@ -0,0 +1,283 @@
|
|||
diff --git a/cmd/access-engine/trusted_service_http_test.go b/cmd/access-engine/trusted_service_http_test.go
|
||||
--- a/cmd/access-engine/trusted_service_http_test.go
|
||||
+++ b/cmd/access-engine/trusted_service_http_test.go
|
||||
@@ -33,6 +33,7 @@
|
||||
func trustedRequest(t *testing.T, now time.Time) api.CheckRequest {
|
||||
t.Helper()
|
||||
r := pilotRequest(now)
|
||||
+ r.Context["execution_contract"].(map[string]any)["operation_deadline"] = now.Add(60 * time.Second).UTC().Truncate(time.Second).Format(time.RFC3339)
|
||||
r.Subject.Tenant = r.Tenant
|
||||
r.Resource.Tenant = r.Tenant
|
||||
r.Resource.Attributes["numeric_fixture"] = json.Number("1.0")
|
||||
@@ -44,7 +45,7 @@
|
||||
for _, key := range []string{"ccr_immutable_sha256", "grant_immutable_sha256", "catalog_sha256", "expected_before", "expected_after"} {
|
||||
c[key] = hash
|
||||
}
|
||||
- c["backend_budget"] = map[string]any{"ttl_seconds": json.Number("60"), "uses": json.Number("12")}
|
||||
+ c["backend_budget"] = map[string]any{"ttl_seconds": json.Number("30"), "uses": json.Number("12")}
|
||||
var ops []any
|
||||
for i, method := range []string{"GET", "PUT", "GET", "GET", "PUT", "GET"} {
|
||||
path := "sys/policies/acl/synthetic"
|
||||
@@ -74,7 +75,7 @@
|
||||
binding["pdp_digest"] = api.ApprovalBindingDigest(legacy)
|
||||
binding["pdp_path"] = true
|
||||
binding["human_control"] = true
|
||||
- r.Context["approval"] = map[string]any{"schema_version": "0.1", "kind": "approval-claim", "issuer": "approval-engine", "approval_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee", "state": "valid", "valid_now": true, "consumed": false, "reason_code": "ok", "binding": binding, "freshness": map[string]any{"observed_at": now.Add(-time.Second).Format(time.RFC3339Nano), "ttl_seconds": json.Number("60"), "not_after": now.Add(59 * time.Second).Format(time.RFC3339Nano)}, "validity": map[string]any{"not_before": now.Add(-time.Hour).Format(time.RFC3339Nano), "expires_at": now.Add(time.Hour).Format(time.RFC3339Nano)}}
|
||||
+ r.Context["approval"] = map[string]any{"schema_version": "0.1", "kind": "approval-claim", "issuer": "approval-engine", "approval_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee", "state": "valid", "valid_now": true, "consumed": false, "reason_code": "ok", "binding": binding, "freshness": map[string]any{"observed_at": now.Add(-time.Second).Format(time.RFC3339Nano), "ttl_seconds": json.Number("120"), "not_after": now.Add(119 * time.Second).Format(time.RFC3339Nano)}, "validity": map[string]any{"not_before": now.Add(-time.Hour).Format(time.RFC3339Nano), "expires_at": now.Add(time.Hour).Format(time.RFC3339Nano)}}
|
||||
return r
|
||||
}
|
||||
func TestTrustedServiceActualHTTPPositiveAndRefusals(t *testing.T) {
|
||||
@@ -114,6 +115,12 @@
|
||||
v, _ := approvalfact.DecodeJSON(claimRaw)
|
||||
v.(map[string]any)["consumed"] = true
|
||||
json.NewEncoder(w).Encode(v)
|
||||
+ case "short-fresh":
|
||||
+ v, _ := approvalfact.DecodeJSON(claimRaw)
|
||||
+ fresh := v.(map[string]any)["freshness"].(map[string]any)
|
||||
+ fresh["ttl_seconds"] = json.Number("20")
|
||||
+ fresh["not_after"] = now.Add(19 * time.Second).Format(time.RFC3339Nano)
|
||||
+ json.NewEncoder(w).Encode(v)
|
||||
case "expired":
|
||||
v, _ := approvalfact.DecodeJSON(claimRaw)
|
||||
v.(map[string]any)["freshness"].(map[string]any)["not_after"] = now.Add(-time.Second).Format(time.RFC3339Nano)
|
||||
@@ -186,6 +193,9 @@
|
||||
if !reflect.DeepEqual(envelope.Binding.Context, original.Context) {
|
||||
t.Fatal("original context changed")
|
||||
}
|
||||
+ if envelope.Lifetime.ExpiresAt != original.Context["execution_contract"].(map[string]any)["operation_deadline"] {
|
||||
+ t.Fatal("decision does not bound entire exact operation")
|
||||
+ }
|
||||
if envelope.Binding.Resource.Attributes["numeric_fixture"] != json.Number("1.0") {
|
||||
t.Fatal("native numeric kind lost")
|
||||
}
|
||||
@@ -200,7 +210,7 @@
|
||||
if !reflect.DeepEqual(recordEnvelope, envelope) {
|
||||
t.Fatal("returned/recorded mismatch")
|
||||
}
|
||||
- for _, failure := range []string{"redirect", "duplicate", "changed", "expired"} {
|
||||
+ for _, failure := range []string{"redirect", "duplicate", "changed", "expired", "short-fresh"} {
|
||||
t.Run(failure, func(t *testing.T) {
|
||||
mode = failure
|
||||
status, _ := post(original)
|
||||
@@ -217,7 +227,7 @@
|
||||
t.Fatal(err)
|
||||
}
|
||||
fresh := r.Context["approval"].(map[string]any)["freshness"].(map[string]any)
|
||||
- fresh["observed_at"] = now.Add(-61 * time.Second).Format(time.RFC3339Nano)
|
||||
+ fresh["observed_at"] = now.Add(-121 * time.Second).Format(time.RFC3339Nano)
|
||||
fresh["not_after"] = now.Add(-time.Second).Format(time.RFC3339Nano)
|
||||
status, _ := post(r)
|
||||
if status == 200 {
|
||||
diff --git a/docs/trusted-service-task-source.md b/docs/trusted-service-task-source.md
|
||||
--- a/docs/trusted-service-task-source.md
|
||||
+++ b/docs/trusted-service-task-source.md
|
||||
@@ -44,9 +44,21 @@
|
||||
batch and list entry points refuse task execution across all policy names. No
|
||||
request-selected verified flag, provider origin or policy enable switch bypasses
|
||||
the typed path. Missing approval can receive signed DENY for preapproval binding;
|
||||
-ALLOW requires authenticated matching original/fresh claims. Its expiry is capped
|
||||
-by policy TTL, caller expiry, operation deadline and both claims' freshness and
|
||||
-validity, rechecked after I/O/evaluation. Existing source-owned signing covers the
|
||||
+ALLOW requires authenticated matching original/fresh claims. Its expiry is exactly the immutable operation deadline, after validating that
|
||||
+it fits the source-selected 120s hard maximum and every caller/original/fresh
|
||||
+freshness/approval bound. At least the declared backend TTL plus the existing
|
||||
+5s cleanup reserve must still fit after source I/O and final evaluation. The
|
||||
+source maximum conservatively matches the existing 120s task-token cap; the
|
||||
+structural backend budget maximum is not a promise every budget can fit. In
|
||||
+particular backend TTL120 cannot fit this authority ceiling plus reserve. A
|
||||
+fractional operation deadline is retained exactly rather than rounded earlier.
|
||||
+Approval's default 30s observation freshness cannot cover the minimum30+5
|
||||
+operation budget. A separate owner-admitted source configuration must explicitly
|
||||
+supply adequate original/fresh observation lifetime; fetching anew cannot renew
|
||||
+an original claim. The disposable reviewed proof uses backendTTL30, immutable
|
||||
+operationdeadline+60s and explicitly configured Approval freshness120. This is
|
||||
+an entire-operation authority interval, not a decision-to-start window. Platform
|
||||
+must retain native-entry and per-call deadline/cleanup gates; delays simply refuse. Existing source-owned signing covers the
|
||||
original binding and new `provenance.approval_observation` receipt. The receipt
|
||||
contains source/configuration identity, exact fetched-byte digest, native digest
|
||||
and observation/validation/deadline timestamps. JSONL readback and outbox replay
|
||||
diff --git a/examples/secrets-engine-service-task-execution-v2/policy_package.md b/examples/secrets-engine-service-task-execution-v2/policy_package.md
|
||||
--- a/examples/secrets-engine-service-task-execution-v2/policy_package.md
|
||||
+++ b/examples/secrets-engine-service-task-execution-v2/policy_package.md
|
||||
@@ -5,7 +5,7 @@
|
||||
version: v2
|
||||
status: proposed
|
||||
package: flexauth.secrets_engine.service_task_execution
|
||||
-allow_ttl: 15s
|
||||
+allow_ttl: 120s
|
||||
actions: [execute-ccr]
|
||||
owner: team:platform-security
|
||||
fixtures: [policy_fixtures.yaml]
|
||||
@@ -22,6 +22,11 @@
|
||||
path requires exact TokenReview caller mapping, immutable numeric source
|
||||
representations, a fixed authenticated Approval reader, separate original and
|
||||
fresh claim validation and native/PDP correspondence before policy evaluation.
|
||||
+Its 120s declared TTL is a hard source ceiling, not a blanket grant. The typed
|
||||
+path derives actual expiry exactly from the immutable operation deadline and
|
||||
+requires the entire declared backend TTL plus the existing 5s cleanup reserve
|
||||
+within original/fresh claim, approval and caller bounds. Budgets that cannot fit
|
||||
+refuse; the 120s structural backend maximum is not guaranteed admissible.
|
||||
Generic check, batch and list routes refuse task execution. Selecting this source
|
||||
package alone cannot bypass those joins. No deployment or trust admission is
|
||||
established by this package. The v1 package remains unchanged and DENY-only.
|
||||
@@ -84,6 +89,8 @@
|
||||
not input.context.delegation
|
||||
input.resource.attributes.stage == "prod"
|
||||
time.parse_rfc3339_ns(c.operation_deadline) > time.now_ns()
|
||||
+ time.parse_rfc3339_ns(c.operation_deadline) <= time.now_ns() + 120000000000
|
||||
+ time.parse_rfc3339_ns(c.operation_deadline) >= time.now_ns() + (c.backend_budget.ttl_seconds + 5) * 1000000000
|
||||
input.context.approval.schema_version == "0.1"
|
||||
input.context.approval.kind == "approval-claim"
|
||||
input.context.approval.issuer == "approval-engine"
|
||||
@@ -94,6 +101,7 @@
|
||||
hash_ok(input.context.approval.binding.pdp_digest)
|
||||
time.parse_rfc3339_ns(input.context.approval.freshness.not_after) > time.now_ns()
|
||||
time.parse_rfc3339_ns(input.context.approval.validity.expires_at) >= time.parse_rfc3339_ns(c.operation_deadline)
|
||||
+ time.parse_rfc3339_ns(input.context.approval.freshness.not_after) >= time.parse_rfc3339_ns(c.operation_deadline)
|
||||
input.context.approval.binding.human_control == true
|
||||
}
|
||||
|
||||
diff --git a/internal/decision/trusted_service.go b/internal/decision/trusted_service.go
|
||||
--- a/internal/decision/trusted_service.go
|
||||
+++ b/internal/decision/trusted_service.go
|
||||
@@ -143,22 +143,14 @@
|
||||
}
|
||||
envelope.Provenance.ApprovalObservation = approvalEvidence
|
||||
if envelope.Effect == api.DecisionEffectAllow {
|
||||
- if approvalEvidence == nil || envelope.Lifetime == nil || !deadline.After(now) {
|
||||
+ if approvalEvidence == nil || envelope.Lifetime == nil {
|
||||
return api.DecisionEnvelope{}, ErrServicePilotUnavailable
|
||||
}
|
||||
- end, err := time.Parse(time.RFC3339, envelope.Lifetime.ExpiresAt)
|
||||
+ lifetime, err := trustedTaskLifetime(contract, operationEnd, deadline, now, e.policy.Metadata.AllowTTL)
|
||||
if err != nil {
|
||||
return api.DecisionEnvelope{}, err
|
||||
}
|
||||
- if deadline.Before(end) {
|
||||
- end = deadline
|
||||
- }
|
||||
- // Floor expiry to whole seconds, never extend an authoritative deadline.
|
||||
- end = end.Truncate(time.Second)
|
||||
- if !end.After(now) {
|
||||
- return api.DecisionEnvelope{}, ErrServicePilotUnavailable
|
||||
- }
|
||||
- envelope.Lifetime.ExpiresAt = end.UTC().Format(time.RFC3339)
|
||||
+ envelope.Lifetime = lifetime
|
||||
}
|
||||
if err := e.signTaskEnvelope(&envelope); err != nil {
|
||||
return api.DecisionEnvelope{}, err
|
||||
@@ -168,3 +160,34 @@
|
||||
}
|
||||
return envelope, nil
|
||||
}
|
||||
+
|
||||
+// The source ceiling is deliberately no larger than the existing task-token
|
||||
+// ceiling. Structural backend budgets do not guarantee an executable window.
|
||||
+const trustedTaskMaxAuthority = 120 * time.Second
|
||||
+const trustedTaskCleanupReserve = 5 * time.Second
|
||||
+
|
||||
+// trustedTaskLifetime authorizes the entire exact operation, not merely its
|
||||
+// start. It cannot extend any caller, original/fresh fact, or approval bound.
|
||||
+func trustedTaskLifetime(contract map[string]any, operationEnd, authorityEnd, now time.Time, declared string) (*api.DecisionLifetime, error) {
|
||||
+ maximum, err := api.ParseAllowTTL(declared)
|
||||
+ if err != nil || maximum <= 0 || maximum > trustedTaskMaxAuthority || now.IsZero() || operationEnd.After(authorityEnd) || !operationEnd.After(now) || operationEnd.Sub(now) > maximum {
|
||||
+ return nil, ErrServicePilotUnavailable
|
||||
+ }
|
||||
+ budget, ok := contract["backend_budget"].(map[string]any)
|
||||
+ if !ok {
|
||||
+ return nil, ErrServicePilotUnavailable
|
||||
+ }
|
||||
+ number, ok := budget["ttl_seconds"].(json.Number)
|
||||
+ if !ok {
|
||||
+ return nil, ErrServicePilotUnavailable
|
||||
+ }
|
||||
+ seconds, err := number.Int64()
|
||||
+ if err != nil || seconds < 30 || seconds > 120 {
|
||||
+ return nil, ErrServicePilotUnavailable
|
||||
+ }
|
||||
+ remaining := operationEnd.Sub(now)
|
||||
+ if remaining < time.Duration(seconds)*time.Second+trustedTaskCleanupReserve {
|
||||
+ return nil, ErrServicePilotUnavailable
|
||||
+ }
|
||||
+ return &api.DecisionLifetime{Kind: api.DecisionLifetimeTTL, TTL: remaining.String(), NotBefore: now.UTC().Format(time.RFC3339Nano), ExpiresAt: operationEnd.UTC().Format(time.RFC3339Nano)}, nil
|
||||
+}
|
||||
diff --git a/internal/decision/trusted_service_time_test.go b/internal/decision/trusted_service_time_test.go
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/internal/decision/trusted_service_time_test.go
|
||||
@@ -0,0 +1,56 @@
|
||||
+package decision
|
||||
+
|
||||
+import (
|
||||
+ "encoding/json"
|
||||
+ "testing"
|
||||
+ "time"
|
||||
+)
|
||||
+
|
||||
+func TestTrustedTaskWholeOperationLifetime(t *testing.T) {
|
||||
+ now := time.Date(2026, 10, 16, 12, 0, 0, 0, time.UTC)
|
||||
+ contract := func(ttl string) map[string]any {
|
||||
+ return map[string]any{"backend_budget": map[string]any{"ttl_seconds": json.Number(ttl), "uses": json.Number("12")}}
|
||||
+ }
|
||||
+ end := now.Add(60 * time.Second)
|
||||
+ lifetime, err := trustedTaskLifetime(contract("30"), end, now.Add(120*time.Second), now, "120s")
|
||||
+ if err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+ if lifetime.ExpiresAt != end.Format(time.RFC3339) || lifetime.TTL != "1m0s" || lifetime.NotBefore != now.Format(time.RFC3339) {
|
||||
+ t.Fatal("lifetime not derived from exact operation")
|
||||
+ }
|
||||
+ fractional := end.Add(123456789 * time.Nanosecond)
|
||||
+ lifetime, err = trustedTaskLifetime(contract("30"), fractional, fractional, now, "120s")
|
||||
+ if err != nil || lifetime.ExpiresAt != fractional.Format(time.RFC3339Nano) {
|
||||
+ t.Fatal("exact fractional deadline shortened or extended")
|
||||
+ }
|
||||
+ cases := []struct {
|
||||
+ name string
|
||||
+ ttl string
|
||||
+ end, authority, time time.Time
|
||||
+ maximum string
|
||||
+ }{
|
||||
+ {"old-15s-conflict", "30", end, end, now, "15s"},
|
||||
+ {"insufficient-cleanup-reserve", "30", now.Add(35*time.Second - time.Nanosecond), end, now, "120s"},
|
||||
+ {"elapsed-consume-setup", "30", end, end, now.Add(26 * time.Second), "120s"},
|
||||
+ {"expired-operation", "30", now, now, now, "120s"},
|
||||
+ {"source-hard-maximum", "30", now.Add(120*time.Second + time.Nanosecond), now.Add(130 * time.Second), now, "120s"},
|
||||
+ {"attempted-policy-cap-bypass", "30", end, end, now, "121s"},
|
||||
+ {"shorter-original-or-fresh-fact", "30", end, end.Add(-time.Nanosecond), now, "120s"},
|
||||
+ {"structural-120-cannot-fit", "120", now.Add(120 * time.Second), now.Add(120 * time.Second), now, "120s"},
|
||||
+ {"noninteger-structural-ttl", "30.0", end, end, now, "120s"},
|
||||
+ }
|
||||
+ for _, c := range cases {
|
||||
+ t.Run(c.name, func(t *testing.T) {
|
||||
+ if _, err := trustedTaskLifetime(contract(c.ttl), c.end, c.authority, c.time, c.maximum); err == nil {
|
||||
+ t.Fatal("invalid temporal authority accepted")
|
||||
+ }
|
||||
+ })
|
||||
+ }
|
||||
+ if _, err := trustedTaskLifetime(contract("30"), now.Add(35*time.Second), end, now, "120s"); err != nil {
|
||||
+ t.Fatal("exact required lifetime refused")
|
||||
+ }
|
||||
+ if _, err := trustedTaskLifetime(contract("115"), now.Add(120*time.Second), now.Add(120*time.Second), now, "120s"); err != nil {
|
||||
+ t.Fatal("max fitting declared budget refused")
|
||||
+ }
|
||||
+}
|
||||
diff --git a/workplans/FLEX-WP-0024-decision-envelope-authenticity.md b/workplans/FLEX-WP-0024-decision-envelope-authenticity.md
|
||||
--- a/workplans/FLEX-WP-0024-decision-envelope-authenticity.md
|
||||
+++ b/workplans/FLEX-WP-0024-decision-envelope-authenticity.md
|
||||
@@ -248,3 +248,15 @@
|
||||
source proposal requires independent cross-owner review and full consumer/Platform
|
||||
successor integration, then separately admitted runtime custody, source trust,
|
||||
image provenance and rollout. No source-only proof establishes those runtime gates.
|
||||
+
|
||||
+
|
||||
+2026-10-16 B2/B3 R2 temporal correction (R1 retained): whole-stack review exposed
|
||||
+that R1's 15s ALLOW and default Approval freshness30 cannot fit the declared
|
||||
+minimum backendTTL30 plus existing cleanupreserve5. The v2 successor now derives
|
||||
+exact ALLOW expiry from the immutable operationdeadline, requiring all original/
|
||||
+fresh approval/freshness/caller bounds, a conservative source maximum120 and
|
||||
+remaining declaredTTL+5 after source I/O/evaluation. No consumer/native deadline
|
||||
+or cleanup guard is relaxed. Max structural budgets that cannot fit refuse.
|
||||
+The fixture declares backendTTL30/deadline60 and explicit source freshness120;
|
||||
+owner runtime source freshness configuration and full native integration remain
|
||||
+separate reviewed gates. See docs/trusted-service-task-source.md.
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,101 @@
|
|||
"""Disposable synthetic proof: actual Approval App HTTPS -> actual Access serve.
|
||||
No native config, credential environment, approval or backend effect is used.
|
||||
"""
|
||||
import base64, hashlib, http.server, io, json, os, pathlib, socket, ssl, subprocess, sys, tempfile, threading, time
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from wsgiref.simple_server import make_server, WSGIRequestHandler
|
||||
from cryptography import x509
|
||||
from cryptography.x509.oid import NameOID
|
||||
from cryptography.hazmat.primitives import hashes, serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||
sys.path.insert(0, '/home/worsch/approval-engine')
|
||||
sys.path.insert(0, '/home/worsch/secrets-engine/src')
|
||||
from approval_engine.api import App
|
||||
from approval_engine.auth import Identity, StaticTokenAuthenticator
|
||||
from approval_engine.store import Engine
|
||||
from secrets_engine.authorization import request_digest, approval_binding_digest
|
||||
from urllib.request import Request, urlopen
|
||||
from urllib.error import HTTPError
|
||||
|
||||
OUT=pathlib.Path(sys.argv[1]);OUT.mkdir(exist_ok=True)
|
||||
if any(OUT.iterdir()):raise RuntimeError('use a fresh empty proof output directory')
|
||||
def digest(raw):return 'sha256:'+hashlib.sha256(raw).hexdigest()
|
||||
def write(path,raw,mode=0o600):path.write_bytes(raw);path.chmod(mode)
|
||||
def identity(subject,kind,scopes):return Identity(subject=subject,issuer='synthetic-test-only',audiences=('approval-engine',),principal_type=kind,tenant='tenant:platform',roles=frozenset(),scopes=frozenset(scopes),assurance={'level':'synthetic'},evidence_ref='synthetic-test-only',tenant_source='directory')
|
||||
class Quiet(WSGIRequestHandler):
|
||||
def log_message(self,*args):pass
|
||||
class Review(http.server.BaseHTTPRequestHandler):
|
||||
def do_POST(self):
|
||||
raw=self.rfile.read(int(self.headers['Content-Length']));body=json.loads(raw)
|
||||
assert self.path=='/apis/authentication.k8s.io/v1/tokenreviews'
|
||||
assert self.headers['Authorization']=='Bearer synthetic-reviewer'
|
||||
assert body['spec']['audiences']==['flex-auth','access-engine']
|
||||
self.send_response(200);self.send_header('Content-Type','application/json');self.end_headers();self.wfile.write(json.dumps({'status':{'authenticated':True,'audiences':['flex-auth'],'user':{'username':'system:serviceaccount:secrets-engine:secrets-engine'}}}).encode())
|
||||
def log_message(self,*args):pass
|
||||
with tempfile.TemporaryDirectory(prefix='access-actual-python-source-') as folder:
|
||||
root=pathlib.Path(folder);now=datetime.now(timezone.utc)
|
||||
key=rsa.generate_private_key(public_exponent=65537,key_size=2048);name=x509.Name([x509.NameAttribute(NameOID.COMMON_NAME,'localhost')]);cert=(x509.CertificateBuilder().subject_name(name).issuer_name(name).public_key(key.public_key()).serial_number(x509.random_serial_number()).not_valid_before(now-timedelta(minutes=1)).not_valid_after(now+timedelta(hours=1)).add_extension(x509.SubjectAlternativeName([x509.DNSName('localhost')]),critical=False).sign(key,hashes.SHA256()))
|
||||
ca=root/'ca.pem';private=root/'tls-key.pem';write(ca,cert.public_bytes(serialization.Encoding.PEM));write(private,key.private_bytes(serialization.Encoding.PEM,serialization.PrivateFormat.PKCS8,serialization.NoEncryption()))
|
||||
tls=ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER);tls.load_cert_chain(ca,private)
|
||||
ctx=ssl.create_default_context(cafile=str(ca))
|
||||
def start(server):server.socket=tls.wrap_socket(server.socket,server_side=True);threading.Thread(target=server.serve_forever,daemon=True).start();return 'https://localhost:'+str(server.server_port)
|
||||
review=http.server.HTTPServer(('127.0.0.1',0),Review);review_origin=start(review)
|
||||
engine=Engine(root/'approval.sqlite3',freshness_ttl=120)
|
||||
auth=StaticTokenAuthenticator({'synthetic-creator':identity('secrets-engine','service',{'approval:create'}),'synthetic-human':identity('synthetic-human','human',{'approval:approve'}),'synthetic-reader':identity('synthetic-access-reader','service',{'approval:read'})})
|
||||
app=App(engine,auth)
|
||||
source=make_server('127.0.0.1',0,app,handler_class=Quiet);origin=start(source)
|
||||
def source_call(method,path,body,token):
|
||||
request=Request(origin+path,data=json.dumps(body).encode() if body is not None else None,method=method,headers={'Authorization':'Bearer '+token,'Content-Type':'application/json'})
|
||||
with urlopen(request,context=ctx,timeout=3) as response:return response.status,json.load(response)
|
||||
# Reuse existing owner interoperability contract generator; it has synthetic metadata only.
|
||||
generated=subprocess.check_output([sys.executable,'/tmp/access-trusted-b2-b3-r3/tools/service_task_execution_fixture.py'],env={'PATH':os.defpath})
|
||||
request=json.loads(generated)['request'];request['subject']['tenant']='tenant:platform';request['resource']['tenant']='tenant:platform';request['context']['purpose']='actual Python App source-only synthetic proof';del request['context']['approval'];request['context']['execution_contract']['backend_budget']['ttl_seconds']=30;request['context']['execution_contract']['operation_deadline']=(now+timedelta(seconds=60)).replace(microsecond=0).isoformat()
|
||||
seed=root/'seed';write(seed,base64.urlsafe_b64encode(bytes([19])*32).rstrip(b'='),0o440)
|
||||
reviewer_token=root/'review-token';write(reviewer_token,b'synthetic-reviewer',0o440)
|
||||
reader_token=root/'reader-token';write(reader_token,b'synthetic-reader',0o440)
|
||||
registry=root/'registry.json';write(registry,pathlib.Path('/tmp/access-trusted-b2-b3-r3/examples/secrets-engine/registry_snapshot.json').read_bytes())
|
||||
config=root/'source.json';write(config,json.dumps({'source_id':'synthetic-actual-approval-app','source_revision':'actual-owner-python-source-fixture','origin':origin,'store_tenant':'tenant:platform','ca_file':str(ca),'token_file':str(reader_token)}).encode())
|
||||
listener=socket.socket();listener.bind(('127.0.0.1',0));port=listener.getsockname()[1];listener.close()
|
||||
record=root/'record.jsonl';url=f'http://127.0.0.1:{port}'
|
||||
command=['/tmp/netkingdom-access-trusted-r3','serve','--addr',f'127.0.0.1:{port}','--registry',str(registry),'--policy','/tmp/access-trusted-b2-b3-r3/examples/secrets-engine-service-task-execution-v2/policy_package.md','--log',str(record),'--caller-auth-mode','enforce','--caller-audience','flex-auth','--caller-kubernetes-url',review_origin,'--caller-reviewer-token-file',str(reviewer_token),'--caller-ca-file',str(ca),'--caller-binding','secrets-engine=system:serviceaccount:secrets-engine:secrets-engine','--envelope-signing-key-file',str(seed),'--envelope-signing-kid','synthetic-v2','--approval-source-file',str(config)]
|
||||
child=subprocess.Popen(command,env={},stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL)
|
||||
try:
|
||||
for _ in range(100):
|
||||
try:
|
||||
with urlopen(url+'/healthz',timeout=.2):break
|
||||
except Exception:time.sleep(.02)
|
||||
jwt='synthetic.'+base64.urlsafe_b64encode(json.dumps({'exp':int((now+timedelta(minutes=2)).timestamp())}).encode()).decode().rstrip('=')+'.synthetic'
|
||||
def check(value):
|
||||
req=Request(url+'/v1/check',data=json.dumps(value).encode(),headers={'Authorization':'Bearer '+jwt,'Content-Type':'application/json'})
|
||||
try:
|
||||
with urlopen(req,timeout=5) as response:return response.status,response.read()
|
||||
except HTTPError as error:return error.code,error.read()
|
||||
claimfree=json.loads(json.dumps(request))
|
||||
pre_status,pre_raw=check(claimfree);assert pre_status==200,(pre_status,pre_raw)
|
||||
pre_file=root/'preapproval.json';write(pre_file,pre_raw)
|
||||
subprocess.run(['/tmp/netkingdom-access-owner-proof-verifier',str(pre_file),'/home/worsch/the-custodian/docs/changes/netkingdom-target-2026-10-16/access-native-source/b2-b3/r2/actual-python-source/synthetic-public-trust.json',str(pre_file)],env={},check=True,stdout=subprocess.DEVNULL)
|
||||
pre=json.loads(pre_raw);assert pre['effect']=='deny' and 'lifetime' not in pre and pre['signature']['mode']=='signed'
|
||||
assert pre['binding']['submitted_request_digest']==request_digest(claimfree)
|
||||
assert pre['binding']['request_digest']==pre['binding']['approval_binding_digest']!=request_digest(claimfree)
|
||||
assert pre['binding']['context']==claimfree['context'] and pre['diagnostics']['registry_subject'] is True
|
||||
assert pre['provenance']['policy_package']=='secrets-engine.task-execution.service-pilot' and pre['provenance']['policy_version']=='v2'
|
||||
assert pre['provenance']['policy_package_digest']=='sha256:de5683e5a34161b9349b10cd8e4abef704e0136e3b14b97719fcd7a79850fc4d'
|
||||
native={'action':pre['binding']['action'],'actor':pre['binding']['subject']['id'],'principal':pre['binding']['subject'].get('attributes',{}).get('principal') or pre['binding']['subject']['id'],'purpose':pre['binding']['context']['purpose'],'target':pre['binding']['resource']}
|
||||
aid='aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee'
|
||||
status,created=source_call('POST','/v1/approvals',{'id':aid,'binding':native,'validity':{'not_before':(now-timedelta(minutes=1)).isoformat(),'expires_at':(now+timedelta(minutes=3)).isoformat()},'required_count':1,'pdp_digest':pre['binding']['approval_binding_digest'],'pdp_path':True,'human_control':True},'synthetic-creator');assert status==201
|
||||
status,_=source_call('POST',f'/v1/approvals/{aid}/entries',{},'synthetic-human');assert status==200
|
||||
status,claim=source_call('GET',f'/v1/approvals/{aid}/claim',None,'synthetic-reader');assert status==200 and claim['valid_now'] is True and claim['binding']['human_control'] is True
|
||||
request['context']['approval']=claim
|
||||
status,raw=check(request);assert status==200,(status,raw)
|
||||
response=json.loads(raw);assert response['effect']=='allow' and response['signature']['mode']=='signed'
|
||||
assert response['lifetime']['expires_at']==request['context']['execution_contract']['operation_deadline'].replace('+00:00','Z');assert response['binding']['context']==request['context'];assert response['binding']['submitted_request_digest']==request_digest(request);assert response['binding']['approval_binding_digest']==pre['binding']['approval_binding_digest']
|
||||
assert response['provenance']['approval_observation']['source_id']=='synthetic-actual-approval-app'
|
||||
saved=record.read_bytes();records=[json.loads(line) for line in saved.splitlines()];assert len(records)==2 and records[0]==pre and records[1]==response
|
||||
# Actual producer state transition is fetched anew and cannot be rescued by carried claim.
|
||||
engine.revoke(aid)
|
||||
refused,_=check(request);assert refused!=200 and record.read_bytes()==saved
|
||||
for name,value in [('request.json',request),('response.json',response),('source-record.json',records[1]),('preapproval-receipt.json',pre),('preapproval-source-record.json',records[0]),('claimfree-request.json',claimfree),('original-approval-claim.json',claim)]:write(OUT/name,(json.dumps(value,indent=2)+'\n').encode(),0o644)
|
||||
receipt={'scope':'disposable synthetic only','actual_source':'Approval App over TLS with authenticated create, configured synthetic human entry, read; actual SQLite engine','actual_access':'production serve binary from B2/B3 R3 retained-registry preapproval successor','allow':True,'backend_ttl_seconds':30,'operation_authority_seconds':60,'explicit_approval_freshness_seconds':120,'decision_expiry_equals_exact_operation_deadline':True,'original_context_unchanged':True,'published_digest_match':True,'returned_source_record_match':True,'actual_source_revoke_refused':True,'no_record_after_refusal':True,'native_admission':False,'retained_registry_sha256':digest(registry.read_bytes()),'signed_deny_supplies_facts_not_execution':True,'approval_issued_from_authenticated_normalized_binding':True,'submitted_proposal_unchanged_except_original_issued_claim':True,'files_sha256':{p.name:digest(p.read_bytes()) for p in OUT.iterdir() if p.suffix=='.json' and p.name!='receipt.json'}}
|
||||
write(OUT/'receipt.json',(json.dumps(receipt,indent=2)+'\n').encode(),0o644);print(json.dumps(receipt,indent=2))
|
||||
finally:
|
||||
child.terminate();child.wait(timeout=5);source.shutdown();review.shutdown();engine.close()
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"existing_producer_signature_verified":true,"independent_synthetic_public_fixture":true,"returned_record_canonical_bytes_match":true,"new_signature_implementation":false}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
{
|
||||
"tenant": "tenant:platform",
|
||||
"subject": {
|
||||
"id": "secrets-engine",
|
||||
"type": "service",
|
||||
"tenant": "tenant:platform"
|
||||
},
|
||||
"action": "execute-ccr",
|
||||
"resource": {
|
||||
"id": "catalog:synthetic",
|
||||
"type": "secret-catalog-lane",
|
||||
"system": "secrets-engine",
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
},
|
||||
"tenant": "tenant:platform"
|
||||
},
|
||||
"context": {
|
||||
"execution_contract": {
|
||||
"backend_budget": {
|
||||
"ttl_seconds": 30,
|
||||
"uses": 12
|
||||
},
|
||||
"backend_origin": "http://127.0.0.1:18200",
|
||||
"catalog_sha256": "sha256:290e55b2258d66980f9443ba7d1436adfc77b8814bd161004d5af2ba272bc9cc",
|
||||
"ccr_id": "CCR-2099-0001",
|
||||
"ccr_immutable_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"cluster_uid": "synthetic-not-native",
|
||||
"contract_version": "SECRETS-EXEC-20261011-v1",
|
||||
"execution_actor": "service:secrets-engine",
|
||||
"execution_grant_ccr_id": "CCR-2099-0002",
|
||||
"expected_after": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"expected_before": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"grant_immutable_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"operation": "metadata-apply-ccr",
|
||||
"operation_deadline": "2026-10-16T14:59:50+00:00",
|
||||
"operation_id": "cbfbced0-09d5-48c8-a1e7-a2ea4dc69153",
|
||||
"operations": [
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
],
|
||||
"source_bundle": {
|
||||
"engine_dispatcher": {
|
||||
"path": "/synthetic/engine_dispatcher.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"platform_mediator": {
|
||||
"path": "/synthetic/platform_mediator.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"policy_auth": {
|
||||
"path": "/synthetic/policy_auth.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"typed_ccr": {
|
||||
"path": "/synthetic/typed_ccr.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
}
|
||||
},
|
||||
"catalog_target": {
|
||||
"lane": "synthetic",
|
||||
"stage": "prod"
|
||||
},
|
||||
"human_control": true,
|
||||
"service_actor_binding": {
|
||||
"version": "proposed-service-task-caller/v1",
|
||||
"transport_principal": "system:serviceaccount:secrets-engine:secrets-engine",
|
||||
"subject_id": "secrets-engine",
|
||||
"subject_type": "service",
|
||||
"tenant": "tenant:platform"
|
||||
},
|
||||
"purpose": "actual Python App source-only synthetic proof"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"approval_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
|
||||
"binding": {
|
||||
"action": "execute-ccr",
|
||||
"actor": "secrets-engine",
|
||||
"digest": "sha256:19cfbe20e156cef1f4c0a37842c47666d2f5b2164d803d77a12346ed38a9444d",
|
||||
"human_control": true,
|
||||
"pdp_digest": "sha256:cb2d195a1f974d8a769ca79c6aa8e2a5e6ee5528ad82a1232c418bd36fd8bf6e",
|
||||
"pdp_path": true,
|
||||
"principal": "secrets-engine",
|
||||
"purpose": "actual Python App source-only synthetic proof",
|
||||
"target": {
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
},
|
||||
"id": "catalog:synthetic",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"type": "secret-catalog-lane"
|
||||
}
|
||||
},
|
||||
"consumed": false,
|
||||
"freshness": {
|
||||
"not_after": "2026-10-16T15:00:50+00:00",
|
||||
"observed_at": "2026-10-16T14:58:50+00:00",
|
||||
"ttl_seconds": 120
|
||||
},
|
||||
"issuer": "approval-engine",
|
||||
"kind": "approval-claim",
|
||||
"reason_code": "ok",
|
||||
"schema_version": "0.1",
|
||||
"state": "valid",
|
||||
"valid_now": true,
|
||||
"validity": {
|
||||
"expires_at": "2026-10-16T15:01:50.071540+00:00",
|
||||
"not_before": "2026-10-16T14:57:50.071540+00:00"
|
||||
},
|
||||
"yields_to": "net-kingdom taxonomy request-claim schema (statute \u00a717; unassigned)"
|
||||
}
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
{
|
||||
"id": "decision:035194cd9fdcc3c1",
|
||||
"contract_version": "flex-auth.decision-record.v1",
|
||||
"effect": "deny",
|
||||
"reason": "service_execution_contract_unmatched",
|
||||
"matched_policy_version": "v2",
|
||||
"matched_rule": "service_execution_contract_unmatched",
|
||||
"resource": {
|
||||
"id": "catalog:synthetic",
|
||||
"type": "secret-catalog-lane",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
}
|
||||
},
|
||||
"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"
|
||||
]
|
||||
}
|
||||
},
|
||||
"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": "execute-ccr",
|
||||
"resource": {
|
||||
"id": "catalog:synthetic",
|
||||
"type": "secret-catalog-lane",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
}
|
||||
},
|
||||
"context": {
|
||||
"catalog_target": {
|
||||
"lane": "synthetic",
|
||||
"stage": "prod"
|
||||
},
|
||||
"execution_contract": {
|
||||
"backend_budget": {
|
||||
"ttl_seconds": 30,
|
||||
"uses": 12
|
||||
},
|
||||
"backend_origin": "http://127.0.0.1:18200",
|
||||
"catalog_sha256": "sha256:290e55b2258d66980f9443ba7d1436adfc77b8814bd161004d5af2ba272bc9cc",
|
||||
"ccr_id": "CCR-2099-0001",
|
||||
"ccr_immutable_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"cluster_uid": "synthetic-not-native",
|
||||
"contract_version": "SECRETS-EXEC-20261011-v1",
|
||||
"execution_actor": "service:secrets-engine",
|
||||
"execution_grant_ccr_id": "CCR-2099-0002",
|
||||
"expected_after": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"expected_before": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"grant_immutable_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"operation": "metadata-apply-ccr",
|
||||
"operation_deadline": "2026-10-16T14:59:50+00:00",
|
||||
"operation_id": "cbfbced0-09d5-48c8-a1e7-a2ea4dc69153",
|
||||
"operations": [
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
],
|
||||
"source_bundle": {
|
||||
"engine_dispatcher": {
|
||||
"path": "/synthetic/engine_dispatcher.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"platform_mediator": {
|
||||
"path": "/synthetic/platform_mediator.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"policy_auth": {
|
||||
"path": "/synthetic/policy_auth.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"typed_ccr": {
|
||||
"path": "/synthetic/typed_ccr.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
}
|
||||
},
|
||||
"human_control": true,
|
||||
"purpose": "actual Python App source-only synthetic proof",
|
||||
"service_actor_binding": {
|
||||
"subject_id": "secrets-engine",
|
||||
"subject_type": "service",
|
||||
"tenant": "tenant:platform",
|
||||
"transport_principal": "system:serviceaccount:secrets-engine:secrets-engine",
|
||||
"version": "proposed-service-task-caller/v1"
|
||||
}
|
||||
},
|
||||
"request_digest": "sha256:cb2d195a1f974d8a769ca79c6aa8e2a5e6ee5528ad82a1232c418bd36fd8bf6e",
|
||||
"approval_binding_digest": "sha256:cb2d195a1f974d8a769ca79c6aa8e2a5e6ee5528ad82a1232c418bd36fd8bf6e",
|
||||
"submitted_request_digest": "sha256:1775bdd19296cb013659bb24a61e76ef252524bd23db674bb58b9429588c2962"
|
||||
},
|
||||
"diagnostics": {
|
||||
"action": "execute-ccr",
|
||||
"matched_relationship": "",
|
||||
"policy_package": "secrets-engine.task-execution.service-pilot",
|
||||
"policy_status": "proposed",
|
||||
"registry_overrode": [],
|
||||
"registry_resource": false,
|
||||
"registry_subject": true
|
||||
},
|
||||
"provenance": {
|
||||
"evaluator": "flex-auth/local",
|
||||
"mode": "standalone",
|
||||
"policy_package": "secrets-engine.task-execution.service-pilot",
|
||||
"policy_version": "v2",
|
||||
"policy_package_digest": "sha256:de5683e5a34161b9349b10cd8e4abef704e0136e3b14b97719fcd7a79850fc4d",
|
||||
"registry_snapshot_digest": "sha256:f5a309bc0b36721fd6d9ad7f53eb21222162bc2eac62a0ab0802a9a1d51340bb",
|
||||
"input_claim_digests": {
|
||||
"context": "sha256:b19fd358cf9b0aced2ad60ac83a3284e1672d158479a4a0f78663bd213b5c810"
|
||||
},
|
||||
"decision_time": "2026-10-16T14:58:50Z",
|
||||
"caller": {
|
||||
"mode": "enforce",
|
||||
"principal": "system:serviceaccount:secrets-engine:secrets-engine",
|
||||
"audience": "flex-auth",
|
||||
"not_after": "2026-10-16T15:00:50Z"
|
||||
}
|
||||
},
|
||||
"signature": {
|
||||
"mode": "signed",
|
||||
"alg": "ed25519",
|
||||
"kid": "synthetic-v2",
|
||||
"value": "jm09aiLHWNgWj7blcFDEtGFfGtWiwtdkWhUQzcFSJ_WgDq2U_QEnaifBaIYWjRuXmw3Ac8aXuaLXvmRiUmzbCQ"
|
||||
},
|
||||
"caring": {
|
||||
"profile": "caring-0.4.0-rc2",
|
||||
"conformance_findings": [
|
||||
{
|
||||
"code": "CARING-DESCRIPTOR-MISSING",
|
||||
"severity": "warning",
|
||||
"message": "no CARING descriptor matched the request",
|
||||
"fields": [
|
||||
"caring_context"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"existing_producer_signature_verified":true,"independent_synthetic_public_fixture":true,"returned_record_canonical_bytes_match":true,"new_signature_implementation":false}
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
{
|
||||
"id": "decision:035194cd9fdcc3c1",
|
||||
"contract_version": "flex-auth.decision-record.v1",
|
||||
"effect": "deny",
|
||||
"reason": "service_execution_contract_unmatched",
|
||||
"matched_policy_version": "v2",
|
||||
"matched_rule": "service_execution_contract_unmatched",
|
||||
"resource": {
|
||||
"id": "catalog:synthetic",
|
||||
"type": "secret-catalog-lane",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
}
|
||||
},
|
||||
"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"
|
||||
]
|
||||
}
|
||||
},
|
||||
"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": "execute-ccr",
|
||||
"resource": {
|
||||
"id": "catalog:synthetic",
|
||||
"type": "secret-catalog-lane",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
}
|
||||
},
|
||||
"context": {
|
||||
"catalog_target": {
|
||||
"lane": "synthetic",
|
||||
"stage": "prod"
|
||||
},
|
||||
"execution_contract": {
|
||||
"backend_budget": {
|
||||
"ttl_seconds": 30,
|
||||
"uses": 12
|
||||
},
|
||||
"backend_origin": "http://127.0.0.1:18200",
|
||||
"catalog_sha256": "sha256:290e55b2258d66980f9443ba7d1436adfc77b8814bd161004d5af2ba272bc9cc",
|
||||
"ccr_id": "CCR-2099-0001",
|
||||
"ccr_immutable_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"cluster_uid": "synthetic-not-native",
|
||||
"contract_version": "SECRETS-EXEC-20261011-v1",
|
||||
"execution_actor": "service:secrets-engine",
|
||||
"execution_grant_ccr_id": "CCR-2099-0002",
|
||||
"expected_after": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"expected_before": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"grant_immutable_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"operation": "metadata-apply-ccr",
|
||||
"operation_deadline": "2026-10-16T14:59:50+00:00",
|
||||
"operation_id": "cbfbced0-09d5-48c8-a1e7-a2ea4dc69153",
|
||||
"operations": [
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
],
|
||||
"source_bundle": {
|
||||
"engine_dispatcher": {
|
||||
"path": "/synthetic/engine_dispatcher.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"platform_mediator": {
|
||||
"path": "/synthetic/platform_mediator.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"policy_auth": {
|
||||
"path": "/synthetic/policy_auth.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"typed_ccr": {
|
||||
"path": "/synthetic/typed_ccr.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
}
|
||||
},
|
||||
"human_control": true,
|
||||
"purpose": "actual Python App source-only synthetic proof",
|
||||
"service_actor_binding": {
|
||||
"subject_id": "secrets-engine",
|
||||
"subject_type": "service",
|
||||
"tenant": "tenant:platform",
|
||||
"transport_principal": "system:serviceaccount:secrets-engine:secrets-engine",
|
||||
"version": "proposed-service-task-caller/v1"
|
||||
}
|
||||
},
|
||||
"request_digest": "sha256:cb2d195a1f974d8a769ca79c6aa8e2a5e6ee5528ad82a1232c418bd36fd8bf6e",
|
||||
"approval_binding_digest": "sha256:cb2d195a1f974d8a769ca79c6aa8e2a5e6ee5528ad82a1232c418bd36fd8bf6e",
|
||||
"submitted_request_digest": "sha256:1775bdd19296cb013659bb24a61e76ef252524bd23db674bb58b9429588c2962"
|
||||
},
|
||||
"diagnostics": {
|
||||
"action": "execute-ccr",
|
||||
"matched_relationship": "",
|
||||
"policy_package": "secrets-engine.task-execution.service-pilot",
|
||||
"policy_status": "proposed",
|
||||
"registry_overrode": [],
|
||||
"registry_resource": false,
|
||||
"registry_subject": true
|
||||
},
|
||||
"provenance": {
|
||||
"evaluator": "flex-auth/local",
|
||||
"mode": "standalone",
|
||||
"policy_package": "secrets-engine.task-execution.service-pilot",
|
||||
"policy_version": "v2",
|
||||
"policy_package_digest": "sha256:de5683e5a34161b9349b10cd8e4abef704e0136e3b14b97719fcd7a79850fc4d",
|
||||
"registry_snapshot_digest": "sha256:f5a309bc0b36721fd6d9ad7f53eb21222162bc2eac62a0ab0802a9a1d51340bb",
|
||||
"input_claim_digests": {
|
||||
"context": "sha256:b19fd358cf9b0aced2ad60ac83a3284e1672d158479a4a0f78663bd213b5c810"
|
||||
},
|
||||
"decision_time": "2026-10-16T14:58:50Z",
|
||||
"caller": {
|
||||
"mode": "enforce",
|
||||
"principal": "system:serviceaccount:secrets-engine:secrets-engine",
|
||||
"audience": "flex-auth",
|
||||
"not_after": "2026-10-16T15:00:50Z"
|
||||
}
|
||||
},
|
||||
"signature": {
|
||||
"mode": "signed",
|
||||
"alg": "ed25519",
|
||||
"kid": "synthetic-v2",
|
||||
"value": "jm09aiLHWNgWj7blcFDEtGFfGtWiwtdkWhUQzcFSJ_WgDq2U_QEnaifBaIYWjRuXmw3Ac8aXuaLXvmRiUmzbCQ"
|
||||
},
|
||||
"caring": {
|
||||
"profile": "caring-0.4.0-rc2",
|
||||
"conformance_findings": [
|
||||
{
|
||||
"code": "CARING-DESCRIPTOR-MISSING",
|
||||
"severity": "warning",
|
||||
"message": "no CARING descriptor matched the request",
|
||||
"fields": [
|
||||
"caring_context"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"scope": "disposable synthetic only",
|
||||
"actual_source": "Approval App over TLS with authenticated create, configured synthetic human entry, read; actual SQLite engine",
|
||||
"actual_access": "production serve binary from B2/B3 R3 retained-registry preapproval successor",
|
||||
"allow": true,
|
||||
"backend_ttl_seconds": 30,
|
||||
"operation_authority_seconds": 60,
|
||||
"explicit_approval_freshness_seconds": 120,
|
||||
"decision_expiry_equals_exact_operation_deadline": true,
|
||||
"original_context_unchanged": true,
|
||||
"published_digest_match": true,
|
||||
"returned_source_record_match": true,
|
||||
"actual_source_revoke_refused": true,
|
||||
"no_record_after_refusal": true,
|
||||
"native_admission": false,
|
||||
"retained_registry_sha256": "sha256:37fba44ec0e0fd9b1e17a05ad1b7e4f9bb6ec9e0fc0bb3133e8af2ac6f832d7c",
|
||||
"signed_deny_supplies_facts_not_execution": true,
|
||||
"approval_issued_from_authenticated_normalized_binding": true,
|
||||
"submitted_proposal_unchanged_except_original_issued_claim": true,
|
||||
"files_sha256": {
|
||||
"preapproval-receipt.json": "sha256:dca4347b07516b2070fb3a80c48649f52fb3b49410eae76f5d8f5b15a79862a5",
|
||||
"preapproval-source-record.json": "sha256:dca4347b07516b2070fb3a80c48649f52fb3b49410eae76f5d8f5b15a79862a5",
|
||||
"source-record.json": "sha256:45da993dae29a881452616be6b13276549116c8e3fb5364016009b422b4a5bcb",
|
||||
"claimfree-request.json": "sha256:398437740393b3a9cc9e6063e8c022b84f587942e71e9f35153c23f128e3f300",
|
||||
"response.json": "sha256:45da993dae29a881452616be6b13276549116c8e3fb5364016009b422b4a5bcb",
|
||||
"original-approval-claim.json": "sha256:92b646831ab55ce9433f844ea6f7c22be94289b5f118799d17a7044532dccfa4",
|
||||
"request.json": "sha256:323e6309b3c4a5ab45ff54e5850e5a4e3ce001c1dfeb8e6fff69e55a093b275e"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
{
|
||||
"tenant": "tenant:platform",
|
||||
"subject": {
|
||||
"id": "secrets-engine",
|
||||
"type": "service",
|
||||
"tenant": "tenant:platform"
|
||||
},
|
||||
"action": "execute-ccr",
|
||||
"resource": {
|
||||
"id": "catalog:synthetic",
|
||||
"type": "secret-catalog-lane",
|
||||
"system": "secrets-engine",
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
},
|
||||
"tenant": "tenant:platform"
|
||||
},
|
||||
"context": {
|
||||
"execution_contract": {
|
||||
"backend_budget": {
|
||||
"ttl_seconds": 30,
|
||||
"uses": 12
|
||||
},
|
||||
"backend_origin": "http://127.0.0.1:18200",
|
||||
"catalog_sha256": "sha256:290e55b2258d66980f9443ba7d1436adfc77b8814bd161004d5af2ba272bc9cc",
|
||||
"ccr_id": "CCR-2099-0001",
|
||||
"ccr_immutable_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"cluster_uid": "synthetic-not-native",
|
||||
"contract_version": "SECRETS-EXEC-20261011-v1",
|
||||
"execution_actor": "service:secrets-engine",
|
||||
"execution_grant_ccr_id": "CCR-2099-0002",
|
||||
"expected_after": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"expected_before": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"grant_immutable_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"operation": "metadata-apply-ccr",
|
||||
"operation_deadline": "2026-10-16T14:59:50+00:00",
|
||||
"operation_id": "cbfbced0-09d5-48c8-a1e7-a2ea4dc69153",
|
||||
"operations": [
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
],
|
||||
"source_bundle": {
|
||||
"engine_dispatcher": {
|
||||
"path": "/synthetic/engine_dispatcher.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"platform_mediator": {
|
||||
"path": "/synthetic/platform_mediator.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"policy_auth": {
|
||||
"path": "/synthetic/policy_auth.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"typed_ccr": {
|
||||
"path": "/synthetic/typed_ccr.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
}
|
||||
},
|
||||
"catalog_target": {
|
||||
"lane": "synthetic",
|
||||
"stage": "prod"
|
||||
},
|
||||
"human_control": true,
|
||||
"service_actor_binding": {
|
||||
"version": "proposed-service-task-caller/v1",
|
||||
"transport_principal": "system:serviceaccount:secrets-engine:secrets-engine",
|
||||
"subject_id": "secrets-engine",
|
||||
"subject_type": "service",
|
||||
"tenant": "tenant:platform"
|
||||
},
|
||||
"purpose": "actual Python App source-only synthetic proof",
|
||||
"approval": {
|
||||
"approval_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
|
||||
"binding": {
|
||||
"action": "execute-ccr",
|
||||
"actor": "secrets-engine",
|
||||
"digest": "sha256:19cfbe20e156cef1f4c0a37842c47666d2f5b2164d803d77a12346ed38a9444d",
|
||||
"human_control": true,
|
||||
"pdp_digest": "sha256:cb2d195a1f974d8a769ca79c6aa8e2a5e6ee5528ad82a1232c418bd36fd8bf6e",
|
||||
"pdp_path": true,
|
||||
"principal": "secrets-engine",
|
||||
"purpose": "actual Python App source-only synthetic proof",
|
||||
"target": {
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
},
|
||||
"id": "catalog:synthetic",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"type": "secret-catalog-lane"
|
||||
}
|
||||
},
|
||||
"consumed": false,
|
||||
"freshness": {
|
||||
"not_after": "2026-10-16T15:00:50+00:00",
|
||||
"observed_at": "2026-10-16T14:58:50+00:00",
|
||||
"ttl_seconds": 120
|
||||
},
|
||||
"issuer": "approval-engine",
|
||||
"kind": "approval-claim",
|
||||
"reason_code": "ok",
|
||||
"schema_version": "0.1",
|
||||
"state": "valid",
|
||||
"valid_now": true,
|
||||
"validity": {
|
||||
"expires_at": "2026-10-16T15:01:50.071540+00:00",
|
||||
"not_before": "2026-10-16T14:57:50.071540+00:00"
|
||||
},
|
||||
"yields_to": "net-kingdom taxonomy request-claim schema (statute \u00a717; unassigned)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,251 @@
|
|||
{
|
||||
"id": "decision:d4c3d2d2f6827449",
|
||||
"contract_version": "flex-auth.decision-record.v1",
|
||||
"effect": "allow",
|
||||
"reason": "exact_task_execution_matched",
|
||||
"matched_policy_version": "v2",
|
||||
"matched_rule": "exact_task_execution_matched",
|
||||
"resource": {
|
||||
"id": "catalog:synthetic",
|
||||
"type": "secret-catalog-lane",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
}
|
||||
},
|
||||
"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"
|
||||
]
|
||||
}
|
||||
},
|
||||
"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": "execute-ccr",
|
||||
"resource": {
|
||||
"id": "catalog:synthetic",
|
||||
"type": "secret-catalog-lane",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
}
|
||||
},
|
||||
"context": {
|
||||
"approval": {
|
||||
"approval_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
|
||||
"binding": {
|
||||
"action": "execute-ccr",
|
||||
"actor": "secrets-engine",
|
||||
"digest": "sha256:19cfbe20e156cef1f4c0a37842c47666d2f5b2164d803d77a12346ed38a9444d",
|
||||
"human_control": true,
|
||||
"pdp_digest": "sha256:cb2d195a1f974d8a769ca79c6aa8e2a5e6ee5528ad82a1232c418bd36fd8bf6e",
|
||||
"pdp_path": true,
|
||||
"principal": "secrets-engine",
|
||||
"purpose": "actual Python App source-only synthetic proof",
|
||||
"target": {
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
},
|
||||
"id": "catalog:synthetic",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"type": "secret-catalog-lane"
|
||||
}
|
||||
},
|
||||
"consumed": false,
|
||||
"freshness": {
|
||||
"not_after": "2026-10-16T15:00:50+00:00",
|
||||
"observed_at": "2026-10-16T14:58:50+00:00",
|
||||
"ttl_seconds": 120
|
||||
},
|
||||
"issuer": "approval-engine",
|
||||
"kind": "approval-claim",
|
||||
"reason_code": "ok",
|
||||
"schema_version": "0.1",
|
||||
"state": "valid",
|
||||
"valid_now": true,
|
||||
"validity": {
|
||||
"expires_at": "2026-10-16T15:01:50.071540+00:00",
|
||||
"not_before": "2026-10-16T14:57:50.071540+00:00"
|
||||
},
|
||||
"yields_to": "net-kingdom taxonomy request-claim schema (statute \u00a717; unassigned)"
|
||||
},
|
||||
"catalog_target": {
|
||||
"lane": "synthetic",
|
||||
"stage": "prod"
|
||||
},
|
||||
"execution_contract": {
|
||||
"backend_budget": {
|
||||
"ttl_seconds": 30,
|
||||
"uses": 12
|
||||
},
|
||||
"backend_origin": "http://127.0.0.1:18200",
|
||||
"catalog_sha256": "sha256:290e55b2258d66980f9443ba7d1436adfc77b8814bd161004d5af2ba272bc9cc",
|
||||
"ccr_id": "CCR-2099-0001",
|
||||
"ccr_immutable_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"cluster_uid": "synthetic-not-native",
|
||||
"contract_version": "SECRETS-EXEC-20261011-v1",
|
||||
"execution_actor": "service:secrets-engine",
|
||||
"execution_grant_ccr_id": "CCR-2099-0002",
|
||||
"expected_after": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"expected_before": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"grant_immutable_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"operation": "metadata-apply-ccr",
|
||||
"operation_deadline": "2026-10-16T14:59:50+00:00",
|
||||
"operation_id": "cbfbced0-09d5-48c8-a1e7-a2ea4dc69153",
|
||||
"operations": [
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
],
|
||||
"source_bundle": {
|
||||
"engine_dispatcher": {
|
||||
"path": "/synthetic/engine_dispatcher.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"platform_mediator": {
|
||||
"path": "/synthetic/platform_mediator.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"policy_auth": {
|
||||
"path": "/synthetic/policy_auth.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"typed_ccr": {
|
||||
"path": "/synthetic/typed_ccr.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
}
|
||||
},
|
||||
"human_control": true,
|
||||
"purpose": "actual Python App source-only synthetic proof",
|
||||
"service_actor_binding": {
|
||||
"subject_id": "secrets-engine",
|
||||
"subject_type": "service",
|
||||
"tenant": "tenant:platform",
|
||||
"transport_principal": "system:serviceaccount:secrets-engine:secrets-engine",
|
||||
"version": "proposed-service-task-caller/v1"
|
||||
}
|
||||
},
|
||||
"request_digest": "sha256:fdce7858cbfb3b945694c27a808b3559ca0ad18ff397e88ace1b0a899f57db2a",
|
||||
"approval_binding_digest": "sha256:cb2d195a1f974d8a769ca79c6aa8e2a5e6ee5528ad82a1232c418bd36fd8bf6e",
|
||||
"submitted_request_digest": "sha256:55da69cfae4f20000177333d27d97c739e6ad55609f5fefe7f7b83503d7da4b5"
|
||||
},
|
||||
"lifetime": {
|
||||
"kind": "ttl",
|
||||
"ttl": "59.4099177s",
|
||||
"not_before": "2026-10-16T14:58:50.5900823Z",
|
||||
"expires_at": "2026-10-16T14:59:50Z"
|
||||
},
|
||||
"diagnostics": {
|
||||
"action": "execute-ccr",
|
||||
"matched_relationship": "",
|
||||
"policy_package": "secrets-engine.task-execution.service-pilot",
|
||||
"policy_status": "proposed",
|
||||
"registry_overrode": [],
|
||||
"registry_resource": false,
|
||||
"registry_subject": true
|
||||
},
|
||||
"provenance": {
|
||||
"evaluator": "flex-auth/local",
|
||||
"mode": "standalone",
|
||||
"policy_package": "secrets-engine.task-execution.service-pilot",
|
||||
"policy_version": "v2",
|
||||
"policy_package_digest": "sha256:de5683e5a34161b9349b10cd8e4abef704e0136e3b14b97719fcd7a79850fc4d",
|
||||
"registry_snapshot_digest": "sha256:f5a309bc0b36721fd6d9ad7f53eb21222162bc2eac62a0ab0802a9a1d51340bb",
|
||||
"input_claim_digests": {
|
||||
"context": "sha256:3ccefed2cbf9583b74cd5dd1ed92c345f3612f2bdac965e111aeab96da029c27"
|
||||
},
|
||||
"decision_time": "2026-10-16T14:58:50Z",
|
||||
"approval_observation": {
|
||||
"source_id": "synthetic-actual-approval-app",
|
||||
"source_revision": "actual-owner-python-source-fixture",
|
||||
"configuration_digest": "sha256:fc4603a7a332ca886d7024b9bb16d76e82c467fc39048e2bcc7e0c8758a09f34",
|
||||
"claim_digest": "sha256:51f0d25dd1dfaf28b6b411b1165976cfe028e7833ef4143d38fd5f35632d1b19",
|
||||
"native_binding_digest": "sha256:19cfbe20e156cef1f4c0a37842c47666d2f5b2164d803d77a12346ed38a9444d",
|
||||
"observed_at": "2026-10-16T14:58:50Z",
|
||||
"not_after": "2026-10-16T15:00:50Z",
|
||||
"validated_at": "2026-10-16T14:58:50.578384809Z"
|
||||
},
|
||||
"caller": {
|
||||
"mode": "enforce",
|
||||
"principal": "system:serviceaccount:secrets-engine:secrets-engine",
|
||||
"audience": "flex-auth",
|
||||
"not_after": "2026-10-16T15:00:50Z"
|
||||
}
|
||||
},
|
||||
"signature": {
|
||||
"mode": "signed",
|
||||
"alg": "ed25519",
|
||||
"kid": "synthetic-v2",
|
||||
"value": "tXOZgp1hZBoQBLg2ExMR404JIpUSCphWFAtV0z5IMezj-gm_Z2n9Z9Tv9L_qyef47CGjHyB64nReaVVez8FdDA"
|
||||
},
|
||||
"caring": {
|
||||
"profile": "caring-0.4.0-rc2",
|
||||
"conformance_findings": [
|
||||
{
|
||||
"code": "CARING-DESCRIPTOR-MISSING",
|
||||
"severity": "warning",
|
||||
"message": "no CARING descriptor matched the request",
|
||||
"fields": [
|
||||
"caring_context"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,251 @@
|
|||
{
|
||||
"id": "decision:d4c3d2d2f6827449",
|
||||
"contract_version": "flex-auth.decision-record.v1",
|
||||
"effect": "allow",
|
||||
"reason": "exact_task_execution_matched",
|
||||
"matched_policy_version": "v2",
|
||||
"matched_rule": "exact_task_execution_matched",
|
||||
"resource": {
|
||||
"id": "catalog:synthetic",
|
||||
"type": "secret-catalog-lane",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
}
|
||||
},
|
||||
"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"
|
||||
]
|
||||
}
|
||||
},
|
||||
"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": "execute-ccr",
|
||||
"resource": {
|
||||
"id": "catalog:synthetic",
|
||||
"type": "secret-catalog-lane",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
}
|
||||
},
|
||||
"context": {
|
||||
"approval": {
|
||||
"approval_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
|
||||
"binding": {
|
||||
"action": "execute-ccr",
|
||||
"actor": "secrets-engine",
|
||||
"digest": "sha256:19cfbe20e156cef1f4c0a37842c47666d2f5b2164d803d77a12346ed38a9444d",
|
||||
"human_control": true,
|
||||
"pdp_digest": "sha256:cb2d195a1f974d8a769ca79c6aa8e2a5e6ee5528ad82a1232c418bd36fd8bf6e",
|
||||
"pdp_path": true,
|
||||
"principal": "secrets-engine",
|
||||
"purpose": "actual Python App source-only synthetic proof",
|
||||
"target": {
|
||||
"attributes": {
|
||||
"stage": "prod"
|
||||
},
|
||||
"id": "catalog:synthetic",
|
||||
"system": "secrets-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"type": "secret-catalog-lane"
|
||||
}
|
||||
},
|
||||
"consumed": false,
|
||||
"freshness": {
|
||||
"not_after": "2026-10-16T15:00:50+00:00",
|
||||
"observed_at": "2026-10-16T14:58:50+00:00",
|
||||
"ttl_seconds": 120
|
||||
},
|
||||
"issuer": "approval-engine",
|
||||
"kind": "approval-claim",
|
||||
"reason_code": "ok",
|
||||
"schema_version": "0.1",
|
||||
"state": "valid",
|
||||
"valid_now": true,
|
||||
"validity": {
|
||||
"expires_at": "2026-10-16T15:01:50.071540+00:00",
|
||||
"not_before": "2026-10-16T14:57:50.071540+00:00"
|
||||
},
|
||||
"yields_to": "net-kingdom taxonomy request-claim schema (statute \u00a717; unassigned)"
|
||||
},
|
||||
"catalog_target": {
|
||||
"lane": "synthetic",
|
||||
"stage": "prod"
|
||||
},
|
||||
"execution_contract": {
|
||||
"backend_budget": {
|
||||
"ttl_seconds": 30,
|
||||
"uses": 12
|
||||
},
|
||||
"backend_origin": "http://127.0.0.1:18200",
|
||||
"catalog_sha256": "sha256:290e55b2258d66980f9443ba7d1436adfc77b8814bd161004d5af2ba272bc9cc",
|
||||
"ccr_id": "CCR-2099-0001",
|
||||
"ccr_immutable_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"cluster_uid": "synthetic-not-native",
|
||||
"contract_version": "SECRETS-EXEC-20261011-v1",
|
||||
"execution_actor": "service:secrets-engine",
|
||||
"execution_grant_ccr_id": "CCR-2099-0002",
|
||||
"expected_after": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"expected_before": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"grant_immutable_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"operation": "metadata-apply-ccr",
|
||||
"operation_deadline": "2026-10-16T14:59:50+00:00",
|
||||
"operation_id": "cbfbced0-09d5-48c8-a1e7-a2ea4dc69153",
|
||||
"operations": [
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "sys/policies/acl/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "auth/synthetic/role/synthetic",
|
||||
"payload_sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
],
|
||||
"source_bundle": {
|
||||
"engine_dispatcher": {
|
||||
"path": "/synthetic/engine_dispatcher.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"platform_mediator": {
|
||||
"path": "/synthetic/platform_mediator.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"policy_auth": {
|
||||
"path": "/synthetic/policy_auth.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
},
|
||||
"typed_ccr": {
|
||||
"path": "/synthetic/typed_ccr.py",
|
||||
"sha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
}
|
||||
},
|
||||
"human_control": true,
|
||||
"purpose": "actual Python App source-only synthetic proof",
|
||||
"service_actor_binding": {
|
||||
"subject_id": "secrets-engine",
|
||||
"subject_type": "service",
|
||||
"tenant": "tenant:platform",
|
||||
"transport_principal": "system:serviceaccount:secrets-engine:secrets-engine",
|
||||
"version": "proposed-service-task-caller/v1"
|
||||
}
|
||||
},
|
||||
"request_digest": "sha256:fdce7858cbfb3b945694c27a808b3559ca0ad18ff397e88ace1b0a899f57db2a",
|
||||
"approval_binding_digest": "sha256:cb2d195a1f974d8a769ca79c6aa8e2a5e6ee5528ad82a1232c418bd36fd8bf6e",
|
||||
"submitted_request_digest": "sha256:55da69cfae4f20000177333d27d97c739e6ad55609f5fefe7f7b83503d7da4b5"
|
||||
},
|
||||
"lifetime": {
|
||||
"kind": "ttl",
|
||||
"ttl": "59.4099177s",
|
||||
"not_before": "2026-10-16T14:58:50.5900823Z",
|
||||
"expires_at": "2026-10-16T14:59:50Z"
|
||||
},
|
||||
"diagnostics": {
|
||||
"action": "execute-ccr",
|
||||
"matched_relationship": "",
|
||||
"policy_package": "secrets-engine.task-execution.service-pilot",
|
||||
"policy_status": "proposed",
|
||||
"registry_overrode": [],
|
||||
"registry_resource": false,
|
||||
"registry_subject": true
|
||||
},
|
||||
"provenance": {
|
||||
"evaluator": "flex-auth/local",
|
||||
"mode": "standalone",
|
||||
"policy_package": "secrets-engine.task-execution.service-pilot",
|
||||
"policy_version": "v2",
|
||||
"policy_package_digest": "sha256:de5683e5a34161b9349b10cd8e4abef704e0136e3b14b97719fcd7a79850fc4d",
|
||||
"registry_snapshot_digest": "sha256:f5a309bc0b36721fd6d9ad7f53eb21222162bc2eac62a0ab0802a9a1d51340bb",
|
||||
"input_claim_digests": {
|
||||
"context": "sha256:3ccefed2cbf9583b74cd5dd1ed92c345f3612f2bdac965e111aeab96da029c27"
|
||||
},
|
||||
"decision_time": "2026-10-16T14:58:50Z",
|
||||
"approval_observation": {
|
||||
"source_id": "synthetic-actual-approval-app",
|
||||
"source_revision": "actual-owner-python-source-fixture",
|
||||
"configuration_digest": "sha256:fc4603a7a332ca886d7024b9bb16d76e82c467fc39048e2bcc7e0c8758a09f34",
|
||||
"claim_digest": "sha256:51f0d25dd1dfaf28b6b411b1165976cfe028e7833ef4143d38fd5f35632d1b19",
|
||||
"native_binding_digest": "sha256:19cfbe20e156cef1f4c0a37842c47666d2f5b2164d803d77a12346ed38a9444d",
|
||||
"observed_at": "2026-10-16T14:58:50Z",
|
||||
"not_after": "2026-10-16T15:00:50Z",
|
||||
"validated_at": "2026-10-16T14:58:50.578384809Z"
|
||||
},
|
||||
"caller": {
|
||||
"mode": "enforce",
|
||||
"principal": "system:serviceaccount:secrets-engine:secrets-engine",
|
||||
"audience": "flex-auth",
|
||||
"not_after": "2026-10-16T15:00:50Z"
|
||||
}
|
||||
},
|
||||
"signature": {
|
||||
"mode": "signed",
|
||||
"alg": "ed25519",
|
||||
"kid": "synthetic-v2",
|
||||
"value": "tXOZgp1hZBoQBLg2ExMR404JIpUSCphWFAtV0z5IMezj-gm_Z2n9Z9Tv9L_qyef47CGjHyB64nReaVVez8FdDA"
|
||||
},
|
||||
"caring": {
|
||||
"profile": "caring-0.4.0-rc2",
|
||||
"conformance_findings": [
|
||||
{
|
||||
"code": "CARING-DESCRIPTOR-MISSING",
|
||||
"severity": "warning",
|
||||
"message": "no CARING descriptor matched the request",
|
||||
"fields": [
|
||||
"caring_context"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"outcome":"retained-registry Access ALLOW returned, proof assertion failed before recording passing evidence","reason":"inherited empty-registry harness incorrectly compared evaluated approval-free digest with locally computed original proposal digest","correction":"assert exact equality with authenticated producer preapproval receipt used at actual issue; retain separate original submitted digest assertion","native_effects":false}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"owner": "Access Engine",
|
||||
"status": "source proposal for independent review",
|
||||
"base": "B2/B3 R2; prior failures/R1/R2 evidence retained",
|
||||
"production_change": "existing claim-free typed v2 check emits explicit evaluated approval-free digest in signed DENY normalization receipt; validate fixed native act even before issue",
|
||||
"contract": "docs/request-enrichment.md already requires issuer records producer output, never consumer recomputation of evaluated digest",
|
||||
"preserved": [
|
||||
"retained registry bytes and authoritative enrichment",
|
||||
"original claim-free proposal plus only original issued claim at final submit",
|
||||
"same policy/evaluator and exact native/full/submitted/approval-free joins",
|
||||
"fresh original/source validation without rewriting claims",
|
||||
"R2 exact temporal bounds and precise notbefore",
|
||||
"signature/API modules unchanged",
|
||||
"DENY cannot satisfy execution authorization"
|
||||
],
|
||||
"proof": [
|
||||
"actual retained registry HTTP and production serve signed DENY -> normalized native/PDP issue -> signed ALLOW",
|
||||
"actual Python App TLS create/human/read + retained registry production serve proof; beforeissue existing producer signature verifier",
|
||||
"registry drift with same original/fresh claims refuses",
|
||||
"source/staleness/numeric-kind negative cases",
|
||||
"exact response/record parity and producer signature verification"
|
||||
],
|
||||
"secrets_owner_reported_full_strict_proof": {
|
||||
"path": "/home/worsch/the-custodian/docs/changes/netkingdom-target-2026-10-16/decision-trusted-successor/actual-retained-r4/receipt.json",
|
||||
"sha256": "ef95d15bfe0a113ea0791320face5c2448b681c1b9a205837f31ce57102adf90",
|
||||
"scope": "owner-reported actual builder/preapproval/Approval/human/ALLOW/strictCAS/GET; precision not accepted because natural latency crossed second"
|
||||
},
|
||||
"precision": "unresolved Approval seconds truncation; Access does not backdate or relax start; active Approval owner preparing exact timestamp repair",
|
||||
"remaining": [
|
||||
"independent coordinator/source review",
|
||||
"Approval precise timestamp repair and final fast-CAS successor rerun",
|
||||
"Platform full real backend proof with absolute per-call/cleanup budgets",
|
||||
"separately admitted native source/trust/custody/image/rollout"
|
||||
],
|
||||
"native_admission": false
|
||||
}
|
||||
|
|
@ -0,0 +1,269 @@
|
|||
diff --git a/cmd/access-engine/trusted_service_http_test.go b/cmd/access-engine/trusted_service_http_test.go
|
||||
--- a/cmd/access-engine/trusted_service_http_test.go
|
||||
+++ b/cmd/access-engine/trusted_service_http_test.go
|
||||
@@ -78,7 +78,11 @@
|
||||
r.Context["approval"] = map[string]any{"schema_version": "0.1", "kind": "approval-claim", "issuer": "approval-engine", "approval_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee", "state": "valid", "valid_now": true, "consumed": false, "reason_code": "ok", "binding": binding, "freshness": map[string]any{"observed_at": now.Add(-time.Second).Format(time.RFC3339Nano), "ttl_seconds": json.Number("120"), "not_after": now.Add(119 * time.Second).Format(time.RFC3339Nano)}, "validity": map[string]any{"not_before": now.Add(-time.Hour).Format(time.RFC3339Nano), "expires_at": now.Add(time.Hour).Format(time.RFC3339Nano)}}
|
||||
return r
|
||||
}
|
||||
-func TestTrustedServiceActualHTTPPositiveAndRefusals(t *testing.T) {
|
||||
+func TestTrustedServiceActualHTTPPositiveAndRefusals(t *testing.T) { testTrustedServiceHTTP(t, false) }
|
||||
+func TestTrustedServiceRetainedRegistryPreapprovalAndRefusals(t *testing.T) {
|
||||
+ testTrustedServiceHTTP(t, true)
|
||||
+}
|
||||
+func testTrustedServiceHTTP(t *testing.T, retained bool) {
|
||||
now := time.Now().UTC()
|
||||
folder := t.TempDir()
|
||||
reviewer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -94,6 +98,9 @@
|
||||
os.WriteFile(ca, pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: reviewer.Certificate().Raw}), 0600)
|
||||
os.WriteFile(token, []byte("synthetic-reviewer"), 0600)
|
||||
original := trustedRequest(t, now)
|
||||
+ if retained {
|
||||
+ delete(original.Context, "approval")
|
||||
+ }
|
||||
claimRaw, _ := json.Marshal(original.Context["approval"])
|
||||
mode := "ok"
|
||||
reads := 0
|
||||
@@ -142,7 +149,14 @@
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
- engine, err := decision.NewEngine(registry.NewStore(), pkg)
|
||||
+ store := registry.NewStore()
|
||||
+ if retained {
|
||||
+ store, err = registry.LoadFilePreservingNumbers(filepath.Join("..", "..", "examples", "secrets-engine", "registry_snapshot.json"))
|
||||
+ if err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+ }
|
||||
+ engine, err := decision.NewEngine(store, pkg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -169,6 +183,49 @@
|
||||
body, _ := io.ReadAll(response.Body)
|
||||
return response.StatusCode, body
|
||||
}
|
||||
+ var pre api.DecisionEnvelope
|
||||
+ if retained {
|
||||
+ preStatus, preRaw := post(original)
|
||||
+ if preStatus != 200 {
|
||||
+ t.Fatalf("preapproval status%d", preStatus)
|
||||
+ }
|
||||
+ pre, err = sign.DecodeEnvelope(preRaw)
|
||||
+ if err != nil || sign.Verify(pre, map[string]ed25519.PublicKey{"synthetic-v2": key.Public().(ed25519.PublicKey)}) != nil {
|
||||
+ t.Fatal("preapproval not authenticated")
|
||||
+ }
|
||||
+ if pre.Effect != api.DecisionEffectDeny || pre.Lifetime != nil || pre.Binding.ApprovalBindingDigest == "" || pre.Binding.ApprovalBindingDigest != pre.Binding.RequestDigest {
|
||||
+ t.Fatal("preapproval receipt is execution authority or lacks exactclaimfree digest")
|
||||
+ }
|
||||
+ if pre.Diagnostics["registry_subject"] != true || pre.Provenance.RegistrySnapshotDigest != store.Digest() {
|
||||
+ t.Fatal("retained registry not applied")
|
||||
+ }
|
||||
+ rawOriginal, _ := json.Marshal(original)
|
||||
+ var legacyPre api.CheckRequest
|
||||
+ json.Unmarshal(rawOriginal, &legacyPre)
|
||||
+ if pre.Binding.SubmittedRequestDigest != api.RequestDigest(legacyPre) || pre.Binding.RequestDigest == api.RequestDigest(legacyPre) {
|
||||
+ t.Fatal("original/evaluated retained registry distinction lost")
|
||||
+ }
|
||||
+ carried := trustedRequest(t, now).Context["approval"].(map[string]any)
|
||||
+ native := map[string]any{"action": pre.Binding.Action, "actor": pre.Binding.Subject.ID, "principal": "secrets-engine", "purpose": pre.Binding.Context["purpose"], "target": pre.Binding.Resource}
|
||||
+ nativeRaw, _ := json.Marshal(native)
|
||||
+ _, nativeDigest, err := approvalfact.CanonicalBinding(nativeRaw)
|
||||
+ if err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+ native["digest"] = nativeDigest
|
||||
+ native["pdp_digest"] = pre.Binding.ApprovalBindingDigest
|
||||
+ native["pdp_path"] = true
|
||||
+ native["human_control"] = true
|
||||
+ carried["binding"] = native
|
||||
+ original.Context["approval"] = carried
|
||||
+ claimRaw, _ = json.Marshal(carried)
|
||||
+ originalBytes, _ := json.Marshal(original)
|
||||
+ original, err = taskexecution.DecodeTrustedServiceRequest(bytes.NewReader(originalBytes))
|
||||
+ if err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
status, body := post(original)
|
||||
if status != 200 {
|
||||
t.Fatalf("positive status %d: %s", status, body)
|
||||
@@ -187,9 +244,17 @@
|
||||
legacyRaw, _ := json.Marshal(original)
|
||||
var legacyRequest api.CheckRequest
|
||||
json.Unmarshal(legacyRaw, &legacyRequest)
|
||||
- if envelope.Binding.SubmittedRequestDigest != api.RequestDigest(legacyRequest) || envelope.Binding.RequestDigest != api.RequestDigest(legacyRequest) || envelope.Binding.ApprovalBindingDigest != api.ApprovalBindingDigest(legacyRequest) {
|
||||
- t.Fatal("published original/full/approval-free digest profile changed")
|
||||
- }
|
||||
+ if envelope.Binding.SubmittedRequestDigest != api.RequestDigest(legacyRequest) {
|
||||
+ t.Fatal("original submitted digest changed")
|
||||
+ }
|
||||
+ if retained {
|
||||
+ if envelope.Binding.RequestDigest == api.RequestDigest(legacyRequest) || envelope.Binding.ApprovalBindingDigest != pre.Binding.ApprovalBindingDigest {
|
||||
+ t.Fatal("normalized approval correspondence changed")
|
||||
+ }
|
||||
+ } else if envelope.Binding.RequestDigest != api.RequestDigest(legacyRequest) || envelope.Binding.ApprovalBindingDigest != api.ApprovalBindingDigest(legacyRequest) {
|
||||
+ t.Fatal("published digest profile changed")
|
||||
+ }
|
||||
+
|
||||
if !reflect.DeepEqual(envelope.Binding.Context, original.Context) {
|
||||
t.Fatal("original context changed")
|
||||
}
|
||||
@@ -203,12 +268,16 @@
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
- recordEnvelope, err := sign.DecodeEnvelope(bytes.TrimSpace(recorded))
|
||||
- if err != nil {
|
||||
- t.Fatal(err)
|
||||
- }
|
||||
- if !reflect.DeepEqual(recordEnvelope, envelope) {
|
||||
- t.Fatal("returned/recorded mismatch")
|
||||
+ records, err := audit.NewJSONLDecisionLog(record).ReadAll()
|
||||
+ expectedCount := 1
|
||||
+ if retained {
|
||||
+ expectedCount = 2
|
||||
+ }
|
||||
+ if err != nil || len(records) != expectedCount || !reflect.DeepEqual(records[len(records)-1], envelope) {
|
||||
+ t.Fatal("returned record parity")
|
||||
+ }
|
||||
+ if retained && !reflect.DeepEqual(records[0], pre) {
|
||||
+ t.Fatal("preapproval record parity")
|
||||
}
|
||||
for _, failure := range []string{"redirect", "duplicate", "changed", "expired", "short-fresh"} {
|
||||
t.Run(failure, func(t *testing.T) {
|
||||
@@ -220,6 +289,20 @@
|
||||
})
|
||||
}
|
||||
mode = "ok"
|
||||
+ if retained {
|
||||
+ t.Run("registry-drift-cannot-rebind-approved-act", func(t *testing.T) {
|
||||
+ subject, _ := store.Subject("secrets-engine")
|
||||
+ originalSubject := subject
|
||||
+ subject.Roles = append(append([]api.CanonicalRole{}, subject.Roles...), api.CanonicalRole("synthetic-owner-drift"))
|
||||
+ if err := store.PutSubject(subject); err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+ defer store.PutSubject(originalSubject)
|
||||
+ if status, _ := post(original); status == 200 {
|
||||
+ t.Fatal("changed registry silently rebound original/fresh claim")
|
||||
+ }
|
||||
+ })
|
||||
+ }
|
||||
t.Run("original-stale", func(t *testing.T) {
|
||||
raw, _ := json.Marshal(original)
|
||||
r, err := taskexecution.DecodeTrustedServiceRequest(bytes.NewReader(raw))
|
||||
@@ -254,7 +337,14 @@
|
||||
sourceJSON, _ := json.Marshal(taskexecution.ApprovalSourceConfig{SourceID: "synthetic-approval", SourceRevision: "test-source-revision", Origin: provider.URL, StoreTenant: "tenant:platform", CAFile: pca, TokenFile: ptoken})
|
||||
os.WriteFile(sourcePath, sourceJSON, 0600)
|
||||
registryPath := filepath.Join(folder, "registry.json")
|
||||
- os.WriteFile(registryPath, []byte(`{}`), 0600)
|
||||
+ registryBytes := []byte(`{}`)
|
||||
+ if retained {
|
||||
+ registryBytes, err = os.ReadFile(filepath.Join("..", "..", "examples", "secrets-engine", "registry_snapshot.json"))
|
||||
+ if err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+ }
|
||||
+ os.WriteFile(registryPath, registryBytes, 0600)
|
||||
policyPath, _ := filepath.Abs(filepath.Join("..", "..", "examples", "secrets-engine-service-task-execution-v2", "policy_package.md"))
|
||||
cliRecord := filepath.Join(folder, "cli-record.jsonl")
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
diff --git a/docs/trusted-service-task-source.md b/docs/trusted-service-task-source.md
|
||||
--- a/docs/trusted-service-task-source.md
|
||||
+++ b/docs/trusted-service-task-source.md
|
||||
@@ -72,3 +72,37 @@
|
||||
separate owner-admitted runtime operation. The earlier Platform positive proof
|
||||
remains evidence only at its old ec21518e Access pin; its generic synthetic policy
|
||||
is deliberately incompatible with the successor guarded source.
|
||||
+
|
||||
+## Producer normalization before Approval issue
|
||||
+
|
||||
+The retained registry enriches Secrets subject attributes. Consequently the
|
||||
+submitted approval-free digest is not the evaluated approval-free digest. This
|
||||
+is the existing `docs/request-enrichment.md` contract, not a reason to remove
|
||||
+registry facts or copy its enrichment rules into Secrets.
|
||||
+
|
||||
+The existing `/v1/check` typed v2 path accepts the exact original claim-free
|
||||
+proposal and returns a signed DENY containing the authoritative normalized
|
||||
+binding and original `submitted_request_digest`. For this v2 path it also emits
|
||||
+`approval_binding_digest` when claim-free, equal to evaluated `request_digest`.
|
||||
+That is a normalization receipt supplying facts only. It has no ALLOW lifetime
|
||||
+and cannot satisfy execution authorization. Before issue, Secrets authenticates
|
||||
+this receipt using its existing independent producer trust/policy/source pins,
|
||||
+checks original request/context correspondence, caller/deadline/current-time
|
||||
+bounds and normalized self-digests, then derives the native act and issue digest
|
||||
+from the authenticated producer binding. It does not supply expected registry
|
||||
+facts or expected digests to the producer. The Approval API records these exact
|
||||
+facts at issue; human approval follows its unchanged authenticated contract.
|
||||
+
|
||||
+The submitted proposal remains unchanged; the final request attaches only the
|
||||
+original issued claim. Final ALLOW rechecks independent source facts, native/PDP
|
||||
+correspondence, normalization and all temporal/caller conditions. A changed
|
||||
+registry cannot silently refresh or replace an approved act: a changed evaluated
|
||||
+digest/native target refuses even when the freshly fetched claim is still valid.
|
||||
+The source tests cover the retained registry, signed DENY/ALLOW separation,
|
||||
+original/evaluated digest distinction, unchanged context, source/registry pins,
|
||||
+registry drift, stale/refreshed claims and exact response/record parity. Earlier
|
||||
+empty-registry proofs remain explicitly scoped historical source fixtures.
|
||||
+
|
||||
+R3 retains precise decision `not_before`; it does not floor that lower bound to
|
||||
+mask Approval's current whole-second consumption receipt defect. Approval-owner
|
||||
+precision repair and full owner integration remain separate reviewed evidence.
|
||||
diff --git a/internal/decision/trusted_service.go b/internal/decision/trusted_service.go
|
||||
--- a/internal/decision/trusted_service.go
|
||||
+++ b/internal/decision/trusted_service.go
|
||||
@@ -69,6 +69,10 @@
|
||||
if err != nil {
|
||||
return api.DecisionEnvelope{}, err
|
||||
}
|
||||
+ native, err := nativeServiceAct(normalized)
|
||||
+ if err != nil {
|
||||
+ return api.DecisionEnvelope{}, err
|
||||
+ }
|
||||
ctx = callerauth.WithRecord(ctx, input.Caller())
|
||||
var approvalEvidence *api.ApprovalObservationProvenance
|
||||
deadline := input.Caller().NotAfter
|
||||
@@ -89,10 +93,6 @@
|
||||
id, ok := claim["approval_id"].(string)
|
||||
if !ok {
|
||||
return api.DecisionEnvelope{}, taskexecution.ErrApprovalSource
|
||||
- }
|
||||
- native, err := nativeServiceAct(normalized)
|
||||
- if err != nil {
|
||||
- return api.DecisionEnvelope{}, err
|
||||
}
|
||||
originalRaw, err := json.Marshal(carried)
|
||||
if err != nil {
|
||||
@@ -138,9 +138,9 @@
|
||||
envelope := e.envelope(ctx, normalized, submitted, expectation, facts)
|
||||
envelope.Binding.RequestDigest = api.RequestDigest(evaluated)
|
||||
envelope.Binding.SubmittedRequestDigest = api.RequestDigest(original)
|
||||
- if hasClaim {
|
||||
- envelope.Binding.ApprovalBindingDigest = api.ApprovalBindingDigest(evaluated)
|
||||
- }
|
||||
+ // Claim-free signed DENY is the producer-owned normalization receipt used
|
||||
+ // before Approval issue. It supplies facts only, never execution authority.
|
||||
+ envelope.Binding.ApprovalBindingDigest = api.ApprovalBindingDigest(evaluated)
|
||||
envelope.Provenance.ApprovalObservation = approvalEvidence
|
||||
if envelope.Effect == api.DecisionEffectAllow {
|
||||
if approvalEvidence == nil || envelope.Lifetime == nil {
|
||||
diff --git a/workplans/FLEX-WP-0024-decision-envelope-authenticity.md b/workplans/FLEX-WP-0024-decision-envelope-authenticity.md
|
||||
--- a/workplans/FLEX-WP-0024-decision-envelope-authenticity.md
|
||||
+++ b/workplans/FLEX-WP-0024-decision-envelope-authenticity.md
|
||||
@@ -260,3 +260,13 @@
|
||||
The fixture declares backendTTL30/deadline60 and explicit source freshness120;
|
||||
owner runtime source freshness configuration and full native integration remain
|
||||
separate reviewed gates. See docs/trusted-service-task-source.md.
|
||||
+
|
||||
+2026-10-16 B2/B3 R3 follows actual retained-registry integration failure: subject
|
||||
+enrichment changed evaluated approval-free digest from the original proposal.
|
||||
+The existing signed claim-free DENY now explicitly carries v2 approvalfree digest
|
||||
+(equal evaluated requestdigest), enabling producer-owned preapproval facts under
|
||||
+the already published enrichment contract. The final original proposal adds only
|
||||
+the issued claim; registry drift/refreshed facts cannot silently rebind it.
|
||||
+Retained-registry HTTP and production serve proofs and negative joins pass.
|
||||
+R3 preserves precise notbefore pending separate Approval-owner timestamp fidelity
|
||||
+repair; no rounding waiver, copied registry algorithm or empty-registry workaround.
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"schema": "access-engine.b2-source-preparation-manifest.v1",
|
||||
"B1_frozen_delta_sha256": "574c6396f6ea5f9876fef0583f8fdc38da094d0f666cf09922771a6099a9b267",
|
||||
"source_vector_sha256": "dfb0a8810cd91847d7af6a7af6a51607a67a66fad7b86fc57365308c36bd9323",
|
||||
"artifact_sha256": {
|
||||
"raw-representation-results-r1.json": "9ef987a7422bcfc252e40ac32f3ce7802e60b4a775408ab0aaa3af1edaf01989",
|
||||
"run-representation-probe.py": "632050cf7a2be033dff44b06a412f82fe026f6e08d2407ec46970a6d17290ec6",
|
||||
"raw-representation-probe.go": "71221b2339b0f204f776edbf979f4a6d780864faacb52a41410eac09d1c635d9",
|
||||
"trusted-positive-path-r1.json": "0bb33d6f0fe69ea716c15e7ceea4a5d19529c110bcdb2d07b046c6b5ca71a229"
|
||||
},
|
||||
"runtime_source_changes": false,
|
||||
"policy_enablement": false,
|
||||
"live_actions": false
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
// Synthetic representation experiment only. No policy, crypto, credential or transport.
|
||||
package main
|
||||
import("bytes";"encoding/json";"os")
|
||||
type vector struct {Target string `json:"input_target_json"`; Binding string `json:"canonical_binding_utf8"`}
|
||||
func main(){var input struct{Vectors []vector `json:"native_binding_vectors"`};if json.NewDecoder(os.Stdin).Decode(&input)!=nil{os.Exit(2)};rows:=[]map[string]string{}
|
||||
for _,v:=range input.Vectors{var normal any;if json.Unmarshal([]byte(v.Target),&normal)!=nil{os.Exit(2)};defaultTarget,_:=json.Marshal(normal)
|
||||
var numbers any;d:=json.NewDecoder(bytes.NewBufferString(v.Target));d.UseNumber();if d.Decode(&numbers)!=nil{os.Exit(2)};numberTarget,_:=json.Marshal(numbers)
|
||||
var act map[string]json.RawMessage;if json.Unmarshal([]byte(v.Binding),&act)!=nil{os.Exit(2)};act["target"]=json.RawMessage(v.Target);rawAct,_:=json.Marshal(act)
|
||||
rows=append(rows,map[string]string{"raw_target":v.Target,"go_default_target":string(defaultTarget),"use_number_target":string(numberTarget),"raw_message_act_draft":string(rawAct)})
|
||||
};json.NewEncoder(os.Stdout).Encode(rows)
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
{
|
||||
"schema": "access-engine.raw-native-representation-experiment.v1",
|
||||
"source_vectors_sha256": "dfb0a8810cd91847d7af6a7af6a51607a67a66fad7b86fc57365308c36bd9323",
|
||||
"source_vectors_producer_revision": "eece796b8bbee19551f6aa07ad389cbf83cabcdb",
|
||||
"cases": [
|
||||
{
|
||||
"input_target_json": "{\"value\":true}",
|
||||
"producer_native_digest": "sha256:e1f537daa849e5da023efb5f3d62cc33d94cce20f9ca9c5a708c76e225fd702f",
|
||||
"raw_message_draft_matches_owner": true,
|
||||
"use_number_roundtrip_matches_owner": true,
|
||||
"default_float64_roundtrip_matches_owner": true,
|
||||
"go_default_target": "{\"value\":true}",
|
||||
"go_raw_draft": "{\"action\":\"secrets.kv.destroy\",\"actor\":\"agt-secrets-engine\",\"principal\":\"bernd\",\"purpose\":\"rotate-exposed-key\",\"target\":{\"value\":true}}"
|
||||
},
|
||||
{
|
||||
"input_target_json": "{\"value\":1}",
|
||||
"producer_native_digest": "sha256:3a3d2da6267e4b917505a7c2247e6ce36fd8ee074eef37251bcc66839b602332",
|
||||
"raw_message_draft_matches_owner": true,
|
||||
"use_number_roundtrip_matches_owner": true,
|
||||
"default_float64_roundtrip_matches_owner": true,
|
||||
"go_default_target": "{\"value\":1}",
|
||||
"go_raw_draft": "{\"action\":\"secrets.kv.destroy\",\"actor\":\"agt-secrets-engine\",\"principal\":\"bernd\",\"purpose\":\"rotate-exposed-key\",\"target\":{\"value\":1}}"
|
||||
},
|
||||
{
|
||||
"input_target_json": "{\"value\":1.0}",
|
||||
"producer_native_digest": "sha256:21c2cdb9b161071ebfe361e50703511b2abf6c6f327f153282d247aa92c3898e",
|
||||
"raw_message_draft_matches_owner": true,
|
||||
"use_number_roundtrip_matches_owner": true,
|
||||
"default_float64_roundtrip_matches_owner": false,
|
||||
"go_default_target": "{\"value\":1}",
|
||||
"go_raw_draft": "{\"action\":\"secrets.kv.destroy\",\"actor\":\"agt-secrets-engine\",\"principal\":\"bernd\",\"purpose\":\"rotate-exposed-key\",\"target\":{\"value\":1.0}}"
|
||||
},
|
||||
{
|
||||
"input_target_json": "{\"value\":false}",
|
||||
"producer_native_digest": "sha256:278cbcd013f7923db5258dd860f911d688505a8259f15ccb77983b044f312c74",
|
||||
"raw_message_draft_matches_owner": true,
|
||||
"use_number_roundtrip_matches_owner": true,
|
||||
"default_float64_roundtrip_matches_owner": true,
|
||||
"go_default_target": "{\"value\":false}",
|
||||
"go_raw_draft": "{\"action\":\"secrets.kv.destroy\",\"actor\":\"agt-secrets-engine\",\"principal\":\"bernd\",\"purpose\":\"rotate-exposed-key\",\"target\":{\"value\":false}}"
|
||||
},
|
||||
{
|
||||
"input_target_json": "{\"value\":0}",
|
||||
"producer_native_digest": "sha256:e691b8fb55d4bf82a310dee37c045331100c8031e26ea6f51bdcceeeb3b1f20e",
|
||||
"raw_message_draft_matches_owner": true,
|
||||
"use_number_roundtrip_matches_owner": true,
|
||||
"default_float64_roundtrip_matches_owner": true,
|
||||
"go_default_target": "{\"value\":0}",
|
||||
"go_raw_draft": "{\"action\":\"secrets.kv.destroy\",\"actor\":\"agt-secrets-engine\",\"principal\":\"bernd\",\"purpose\":\"rotate-exposed-key\",\"target\":{\"value\":0}}"
|
||||
},
|
||||
{
|
||||
"input_target_json": "{\"value\":-0.0}",
|
||||
"producer_native_digest": "sha256:eccde458c686bff67506bb2d94c750e648a311bf23967cb22b37f11e84b6844f",
|
||||
"raw_message_draft_matches_owner": true,
|
||||
"use_number_roundtrip_matches_owner": true,
|
||||
"default_float64_roundtrip_matches_owner": false,
|
||||
"go_default_target": "{\"value\":-0}",
|
||||
"go_raw_draft": "{\"action\":\"secrets.kv.destroy\",\"actor\":\"agt-secrets-engine\",\"principal\":\"bernd\",\"purpose\":\"rotate-exposed-key\",\"target\":{\"value\":-0.0}}"
|
||||
},
|
||||
{
|
||||
"input_target_json": "{\"value\":1e-7}",
|
||||
"producer_native_digest": "sha256:779042b6c0e675f6aacdcd3a02199aab66f534bb84dd410a95c18657afae563c",
|
||||
"raw_message_draft_matches_owner": true,
|
||||
"use_number_roundtrip_matches_owner": true,
|
||||
"default_float64_roundtrip_matches_owner": true,
|
||||
"go_default_target": "{\"value\":1e-7}",
|
||||
"go_raw_draft": "{\"action\":\"secrets.kv.destroy\",\"actor\":\"agt-secrets-engine\",\"principal\":\"bernd\",\"purpose\":\"rotate-exposed-key\",\"target\":{\"value\":1e-7}}"
|
||||
},
|
||||
{
|
||||
"input_target_json": "{\"value\":1e-6}",
|
||||
"producer_native_digest": "sha256:d021f402231fcd59e764b31e6f08a5298ebb328dfd93da58ecde8feb11fde0b5",
|
||||
"raw_message_draft_matches_owner": true,
|
||||
"use_number_roundtrip_matches_owner": true,
|
||||
"default_float64_roundtrip_matches_owner": true,
|
||||
"go_default_target": "{\"value\":0.000001}",
|
||||
"go_raw_draft": "{\"action\":\"secrets.kv.destroy\",\"actor\":\"agt-secrets-engine\",\"principal\":\"bernd\",\"purpose\":\"rotate-exposed-key\",\"target\":{\"value\":1e-6}}"
|
||||
},
|
||||
{
|
||||
"input_target_json": "{\"value\":1e20}",
|
||||
"producer_native_digest": "sha256:14270ffca4ab10e9d9302d52e988b4aa3e2facd494c12a60e2edafef70277a20",
|
||||
"raw_message_draft_matches_owner": true,
|
||||
"use_number_roundtrip_matches_owner": true,
|
||||
"default_float64_roundtrip_matches_owner": false,
|
||||
"go_default_target": "{\"value\":100000000000000000000}",
|
||||
"go_raw_draft": "{\"action\":\"secrets.kv.destroy\",\"actor\":\"agt-secrets-engine\",\"principal\":\"bernd\",\"purpose\":\"rotate-exposed-key\",\"target\":{\"value\":1e20}}"
|
||||
},
|
||||
{
|
||||
"input_target_json": "{\"value\":1e21}",
|
||||
"producer_native_digest": "sha256:75a60a595b2578430b0be466b6bf9a46b62ddc99bbbcebd7fa0e8d22e3078c0a",
|
||||
"raw_message_draft_matches_owner": true,
|
||||
"use_number_roundtrip_matches_owner": true,
|
||||
"default_float64_roundtrip_matches_owner": true,
|
||||
"go_default_target": "{\"value\":1e+21}",
|
||||
"go_raw_draft": "{\"action\":\"secrets.kv.destroy\",\"actor\":\"agt-secrets-engine\",\"principal\":\"bernd\",\"purpose\":\"rotate-exposed-key\",\"target\":{\"value\":1e21}}"
|
||||
},
|
||||
{
|
||||
"input_target_json": "{\"value\":2.5e-7}",
|
||||
"producer_native_digest": "sha256:50af37ff75a3e7a22629e746f814995c0c2cd96adb7f1ed5b26999b71d0ac498",
|
||||
"raw_message_draft_matches_owner": true,
|
||||
"use_number_roundtrip_matches_owner": true,
|
||||
"default_float64_roundtrip_matches_owner": true,
|
||||
"go_default_target": "{\"value\":2.5e-7}",
|
||||
"go_raw_draft": "{\"action\":\"secrets.kv.destroy\",\"actor\":\"agt-secrets-engine\",\"principal\":\"bernd\",\"purpose\":\"rotate-exposed-key\",\"target\":{\"value\":2.5e-7}}"
|
||||
},
|
||||
{
|
||||
"input_target_json": "{\"value\":9007199254740993}",
|
||||
"producer_native_digest": "sha256:765360dc5a1d949bd114c6b749d83069123d8b4b6b1d939f831428a800f50dab",
|
||||
"raw_message_draft_matches_owner": true,
|
||||
"use_number_roundtrip_matches_owner": true,
|
||||
"default_float64_roundtrip_matches_owner": false,
|
||||
"go_default_target": "{\"value\":9007199254740992}",
|
||||
"go_raw_draft": "{\"action\":\"secrets.kv.destroy\",\"actor\":\"agt-secrets-engine\",\"principal\":\"bernd\",\"purpose\":\"rotate-exposed-key\",\"target\":{\"value\":9007199254740993}}"
|
||||
},
|
||||
{
|
||||
"input_target_json": "{\"html\":\"<>&\", \"unicode\":\"\u00e9\u96ea\ud83d\ude00\", \"separator\":\"\\u2028\\u2029\"}",
|
||||
"producer_native_digest": "sha256:c203d934743e2954342038a3746b6c37a0f3101e886ef855b1c6ad824adf5dea",
|
||||
"raw_message_draft_matches_owner": true,
|
||||
"use_number_roundtrip_matches_owner": true,
|
||||
"default_float64_roundtrip_matches_owner": true,
|
||||
"go_default_target": "{\"html\":\"\\u003c\\u003e\\u0026\",\"separator\":\"\\u2028\\u2029\",\"unicode\":\"\u00e9\u96ea\ud83d\ude00\"}",
|
||||
"go_raw_draft": "{\"action\":\"secrets.kv.destroy\",\"actor\":\"agt-secrets-engine\",\"principal\":\"bernd\",\"purpose\":\"rotate-exposed-key\",\"target\":{\"html\":\"\\u003c\\u003e\\u0026\",\"unicode\":\"\u00e9\u96ea\ud83d\ude00\",\"separator\":\"\\u2028\\u2029\"}}"
|
||||
},
|
||||
{
|
||||
"input_target_json": "{\"b\":[true,1,1.0,null,{\"z\":\"x\",\"a\":\"y\"}],\"a\":{}}",
|
||||
"producer_native_digest": "sha256:56306505c882af6edfae5f3d2a5b42e92737a0859236fe5574a21d1874655d51",
|
||||
"raw_message_draft_matches_owner": true,
|
||||
"use_number_roundtrip_matches_owner": true,
|
||||
"default_float64_roundtrip_matches_owner": false,
|
||||
"go_default_target": "{\"a\":{},\"b\":[true,1,1,null,{\"a\":\"y\",\"z\":\"x\"}]}",
|
||||
"go_raw_draft": "{\"action\":\"secrets.kv.destroy\",\"actor\":\"agt-secrets-engine\",\"principal\":\"bernd\",\"purpose\":\"rotate-exposed-key\",\"target\":{\"b\":[true,1,1.0,null,{\"z\":\"x\",\"a\":\"y\"}],\"a\":{}}}"
|
||||
}
|
||||
],
|
||||
"raw_preservation_passed": 14,
|
||||
"default_roundtrip_mismatches": 5,
|
||||
"boundary": "Synthetic raw draft preservation only. Actual native digest recomputed with Approval owner Python binding_digest; no Go canonicalization implementation or source-origin trust. Does not prove typed Access signed-envelope preservation, registry/compiler correspondence, trusted provider facts or positive eligibility."
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Producer-vector experiment; no runtime source mutation or credential access."""
|
||||
import argparse,hashlib,json,os,subprocess,sys
|
||||
from pathlib import Path
|
||||
p=argparse.ArgumentParser();p.add_argument('--approval-source',type=Path,required=True);p.add_argument('--vectors',type=Path,required=True);p.add_argument('--output',type=Path,required=True);a=p.parse_args()
|
||||
sys.path.insert(0,str(a.approval_source));from approval_engine.binding import binding_digest
|
||||
vectors=json.loads(a.vectors.read_bytes());env={k:os.environ[k] for k in ('PATH','HOME') if k in os.environ};env.update(GOCACHE='/tmp/netkingdom-go-cache',GOFLAGS='-buildvcs=false',GOMAXPROCS='2')
|
||||
probe=Path(__file__).with_name('raw-representation-probe.go')
|
||||
rows=json.loads(subprocess.check_output(['go','run',str(probe)],input=a.vectors.read_bytes(),env=env))
|
||||
results=[]
|
||||
for vector,row in zip(vectors['native_binding_vectors'],rows,strict=True):
|
||||
def owner_digest(target):
|
||||
return binding_digest({**vector['binding'],'target':json.loads(target)})
|
||||
raw_digest=binding_digest(json.loads(row['raw_message_act_draft']))
|
||||
default_digest=owner_digest(row['go_default_target']);number_digest=owner_digest(row['use_number_target'])
|
||||
assert raw_digest==vector['native_digest'];assert number_digest==vector['native_digest']
|
||||
results.append({'input_target_json':vector['input_target_json'],'producer_native_digest':vector['native_digest'],'raw_message_draft_matches_owner':True,'use_number_roundtrip_matches_owner':True,'default_float64_roundtrip_matches_owner':default_digest==vector['native_digest'],'go_default_target':row['go_default_target'],'go_raw_draft':row['raw_message_act_draft']})
|
||||
assert any(not x['default_float64_roundtrip_matches_owner'] for x in results)
|
||||
result={'schema':'access-engine.raw-native-representation-experiment.v1','source_vectors_sha256':hashlib.sha256(a.vectors.read_bytes()).hexdigest(),'source_vectors_producer_revision':vectors['producer_revision'],'cases':results,'raw_preservation_passed':len(results),'default_roundtrip_mismatches':sum(not x['default_float64_roundtrip_matches_owner'] for x in results),'boundary':'Synthetic raw draft preservation only. Actual native digest recomputed with Approval owner Python binding_digest; no Go canonicalization implementation or source-origin trust. Does not prove typed Access signed-envelope preservation, registry/compiler correspondence, trusted provider facts or positive eligibility.'}
|
||||
a.output.write_text(json.dumps(result,indent=2)+'\n');print({'raw_preservation_passed':len(results),'default_roundtrip_mismatches':result['default_roundtrip_mismatches']})
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"schema": "access-engine.ci-public-metadata-read.v1",
|
||||
"observed_at": "2026-10-16T07:34:51.204550+00:00",
|
||||
"credential_use": "none; anonymous requests only, no auth challenge followup",
|
||||
"queries": {
|
||||
"registry_manifest": {
|
||||
"status": 401,
|
||||
"url": "https://forgejo.coulomb.social/v2/coulomb/flex-auth/manifests/main-ec21518",
|
||||
"auth_challenge_present": true
|
||||
},
|
||||
"workflow_runs": {
|
||||
"status": 404,
|
||||
"url": "https://forgejo.coulomb.social/api/v1/repos/coulomb/access-engine/actions/runs?limit=20",
|
||||
"auth_challenge_present": false
|
||||
},
|
||||
"package_versions": {
|
||||
"status": 401,
|
||||
"url": "https://forgejo.coulomb.social/api/v1/packages/coulomb?type=container&q=flex-auth&limit=50",
|
||||
"auth_challenge_present": false
|
||||
}
|
||||
},
|
||||
"local_cached_image_metadata": {
|
||||
"image": "forgejo.coulomb.social/coulomb/flex-auth:main-ec21518",
|
||||
"exit_code": 1,
|
||||
"output": null,
|
||||
"stderr_present": true
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue