Wires the signing-service's production path for ProofedMesh Phase 1: the service now performs a double identity check (Pocket-ID OIDC JWT + K8s ServiceAccount TokenReview), reconciles both against the trust-api `agents` registry, and asks an OPA/Rego policy whether the caller may sign with the requested key_ref. Code - internal/token/pocket_id.go: OIDC-Discovery-backed JWKS validator with automatic kid rotation (coreos/go-oidc). - internal/token/k8s_tokenreview.go: hand-rolled TokenReview client; reads X-Workload-Token, posts to authentication.k8s.io/v1 via the pod's in-cluster SA token + CA. - internal/registry: Postgres resolver for the agents table + in-memory Static resolver for tests. - internal/policy/opa.go: OPA/rego StructuredDecider; input carries both lookups so the policy can enforce identity consistency AND the key_ref ↔ role mapping. - internal/httpapi/sign.go: new structured flow when Validator+TokenReviewer+Registry+StructuredPolicy are all wired; dev path (static bearers + AllowAll) remains intact. - cmd/signing-service/main.go: -pocket-id-issuer, -pocket-id-audience, -k8s-tokenreview, -registry-dsn, -policy-bundle flags. Policy - policies/sinks/signing_service.rego: identities_agree + key_ref_matches_role rules; agent → key_ref prefix map covers approval-service, testagent-transform, dummy-sink. Deploy - deploy/signing-service/01-rbac.yaml: ClusterRole with tokenreviews.create + binding to the signing-service SA. - deploy/signing-service/20-deployment.yaml: adds POCKET_ID_ISSUER, POCKET_ID_AUDIENCE, TRUST_PG_DSN env, projected SA token volume, OPA policy ConfigMap mount, structured flags. - deploy/signing-service/00-serviceaccount.yaml: disables default auto-mount; a projected volume is used. - deploy/signing-service/README.md: documents prod flags + ConfigMap generation. Tests - httptest-mock Pocket-ID (OIDC discovery + JWKS, kid rotation), StaticTokenReviewer fake, Static registry, real Rego policy. - Happy paths: Approval-Service → trust-api/approval-signer-2026-q4; testagent-transform → trust-api/agent-testagent-transform-2026-q4. - Denies: registry mismatch, wrong key_ref for role, missing / bad workload token, bad Pocket-ID token, kid rotation. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|---|---|---|
| .. | ||
| data_sources | ||
| sinks | ||
| transformations | ||
| README.md | ||
ProofedMesh Policies (OPA / Rego)
Rego-Policies für die drei in docs/architecture/v1.1.md Abschnitt 6 definierten Policy-Klassen. Alle Policies nutzen Rego v1 (import rego.v1).
Policy-Klassen
| Klasse | Package-Präfix | Fragt der |
|---|---|---|
| Transformationen | proofedmesh.transformations.<domain> |
Signing Service |
| Senken | proofedmesh.sinks.<sink_id_slug> |
Verification Service / Adapter |
| Datenquellen | proofedmesh.data_sources.<ds_id_slug> |
Session Scope Token Service |
Default in jedem Package ist allow := false — explizites Zulassen ist erforderlich (deny-by-default).
Dateistruktur
policies/
transformations/
expense.rego — v1.0.0/v1.1.0/v1.2.0 map_to_sink + normalize, with allocation-sum invariant
expense_test.rego
per_diem.rego — expense.compute_per_diem (agent-per-diem-calculator → v1.2.0 output)
per_diem_test.rego
sinks/
expense_db_app.rego
expense_db_app_test.rego
data_sources/
expense_db_app.rego
expense_db_app_test.rego
receipts.rego — ds:receipts write (agent-travel) + read-by-content_hash (agent-sink-*)
receipts_test.rego
per_diem_rates.rego — ds:per-diem-rates read (agent-per-diem-calculator only, country+valid_on required)
per_diem_rates_test.rego
Input-Verträge
Transformationen
{
"agent_id": "agent-sink-mapping",
"operation": "expense.map_to_sink",
"input_schema": { "name": "expense.canonical", "version": "1.0.0" },
"output_schema": { "name": "sink.db.expense", "version": "1.0.0" },
"sink_target": "sink:expense-db-app",
"approval": { "allowed_transformations": [...], "allowed_sinks": [...] },
"input_payload": { ... canonical fields ... },
"output_payload": { ... sink fields ... }
}
Senken
{
"agent_id": "agent-sink-posting",
"sink_id": "sink:expense-db-app",
"action": "expense.post",
"payload": { ... sink.db.expense ... },
"approval": { "allowed_sinks": [...] }
}
Datenquellen (für Session Scope Token Service)
{
"agent_id": "agent-travel",
"user_sub": "user-12345",
"session_id": "SES-...",
"data_source": "ds:expense-db-app",
"resource": "project_assignments",
"filters": { "employee_id": "EMP-12345" },
"operation": "read"
}
Zusätzliche Daten (nicht input, sondern über data.* bereitgestellt): data.employee_mapping.by_sub (user_sub → employee_id), data.agent_registry.by_id (Agent-Metadaten), data.sinks.by_id, data.data_sources.by_id. Trust-API lädt diese bei jedem Policy-Call aus Postgres und übergibt sie via OPA Partial-Evaluation oder bei Bedarf als input.data.
Lokal testen
opa test policies/ -v
opa fmt --list --diff policies/ # formatting check
Beides läuft auch in CI (siehe .forgejo/workflows/validate.yml).
Policy-Versionierung
Jede Policy-Datei bekommt bei Breaking Changes eine neue Hauptversion. Historische Versionen bleiben parallel, solange Attestierungen mit policy_version darauf verweisen (Retention 1 Jahr). Rego-Bundles für Deployment werden aus dem jeweiligen Branch gebaut; der SHA-256 des Bundles landet in jeder Decision als policy_version (siehe ADR-0002, Abschnitt „Token-Format").