Adopt shared hourly coordination frame and prepare guarded runtime patches
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a13eab-1e6a-7b33-9c37-372e90ada3a2
This commit is contained in:
parent
a83691398e
commit
2d0681f361
15 changed files with 860 additions and 70 deletions
16
CONFIG.md
16
CONFIG.md
|
|
@ -26,6 +26,7 @@ If yes to any of the above, don't add it here.
|
|||
| CP-NK-004 | KeyCape OIDC hostname | `kc.coulomb.social` | `sso-mfa/k8s/keycape/ingress.yaml`, `sso-mfa/k8s/authelia/configmap.yaml`, `sso-mfa/k8s/keycape/create-secrets.sh` |
|
||||
| CP-NK-005 | Authelia login portal hostname | `auth.coulomb.social` | `sso-mfa/k8s/authelia/ingress.yaml`, `sso-mfa/k8s/authelia/configmap.yaml` |
|
||||
| CP-NK-006 | LLDAP admin web UI hostname | `lldap.coulomb.social` | `sso-mfa/k8s/lldap/ingress.yaml` |
|
||||
| CP-NK-007 | Ecosystem coordination frame | `f = 1h` | `coordination-engine/config/coordination-frame.json` (owner source) |
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -144,3 +145,18 @@ to the parent domain (`coulomb.social`) so the cookie is valid across both
|
|||
is IP-restricted by the `lldap-admin-allowlist` Traefik Middleware (VPN/office
|
||||
CIDRs only). The LDAP port (3890) is cluster-internal only and never exposed
|
||||
via Ingress.
|
||||
|
||||
|
||||
## CP-NK-007 — Ecosystem coordination frame
|
||||
|
||||
**Owner:** coordination-engine. **Initial setting:** `frame_seconds: 3600`.
|
||||
Founder decision 2026-10-15: pace long-term coordination in hourly rather than
|
||||
daily frames. This is an operator-selected pace, not a topology-derived value.
|
||||
The canonical file is `coordination-engine/config/coordination-frame.json`;
|
||||
NetKingdom keeps no independent editable copy.
|
||||
|
||||
Cadence adopters derive heartbeat f, receiver wait 2f and effective deadline
|
||||
3f (including Audit Core's existing 1.5 grace). Change f once, then run
|
||||
`tools/coordination-frame/render.py --write` and `--check`. Generated owner
|
||||
artifacts carry the source digest. Runtime owners deploy reviewed artifacts;
|
||||
source regeneration is not deployment or estate-wide timer adoption.
|
||||
|
|
|
|||
|
|
@ -159,3 +159,16 @@ This profile can become accepted only when:
|
|||
checked with owner-authored class inventories; and
|
||||
- `kings-guard` has been given the canonical coordinates so its handover draft
|
||||
can become historical.
|
||||
|
||||
|
||||
## Coordination-frame configuration — 2026-10-15
|
||||
|
||||
Source owners may derive their cadence timing from the ecosystem coordination
|
||||
frame at `coordination-engine/config/coordination-frame.json`. The operator's
|
||||
current frame is f=1h; the first adopter mapping is heartbeat f, receiver wait
|
||||
2f, and effective missing-heartbeat deadline 3f after the receiver's 1.5 grace.
|
||||
Namespaced frame provenance accompanies the derived numeric declaration values.
|
||||
Changing the frame requires regenerating the source/receiver settings together
|
||||
and separately deploying them through owner change control. It changes neither
|
||||
source classification nor the heartbeat-plus-reconciliation requirement, and
|
||||
a compiled configuration is not evidence of operating emission or observation.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
[
|
||||
{
|
||||
"op": "test",
|
||||
"path": "/metadata/uid",
|
||||
"value": "8b44c901-024f-4472-a822-2fd07aa2be5f"
|
||||
},
|
||||
{
|
||||
"op": "test",
|
||||
"path": "/metadata/resourceVersion",
|
||||
"value": "75292270"
|
||||
},
|
||||
{
|
||||
"op": "add",
|
||||
"path": "/spec/template/metadata/annotations",
|
||||
"value": {
|
||||
"coordination.coulomb.social/frame-sha256": "d15e092387f128ffdfd00b9815707a05ff77c5bb0ba4d9a428fbc37b8c440b67"
|
||||
}
|
||||
},
|
||||
{
|
||||
"op": "add",
|
||||
"path": "/spec/template/spec/containers/0/args/-",
|
||||
"value": "--heartbeat-seconds"
|
||||
},
|
||||
{
|
||||
"op": "add",
|
||||
"path": "/spec/template/spec/containers/0/args/-",
|
||||
"value": "3600"
|
||||
}
|
||||
]
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"workplan_id": "04685f94-1991-5e62-80d2-5669913e99fc",
|
||||
"id": "1ac5a70f-082e-4d8f-9ac8-59e4c175da02",
|
||||
"topic_id": null,
|
||||
"title": "Use a configurable ecosystem coordination frame, initially one hour",
|
||||
"description": "Founder directs one base duration frame for ecosystem coordination timelines and deadlines. Set f=1h now, with waits expressed as 2f and 3f rather than independent day constants. First cadence adoption: heartbeat f, registered receiver wait 2f, existing 1.5 grace yields effective 3f.",
|
||||
"decision_type": "made",
|
||||
"status": "resolved",
|
||||
"rationale": "Small team is moving quickly; long-term coordination currently needs an hourly rather than daily pace. Owner-reviewed adoption retains timing formulas and frame provenance. This records the configuration decision, not an approval of an unspecified live rollout.",
|
||||
"decided_by": "Bernd Worsch (founder), explicit session instruction",
|
||||
"decided_at": "2026-10-15T18:05:48.234679Z",
|
||||
"deadline": null,
|
||||
"escalation_note": null,
|
||||
"superseded_by": null,
|
||||
"created_at": "2026-10-15T18:05:49.826919Z",
|
||||
"updated_at": "2026-10-15T18:05:49.826919Z",
|
||||
"workstream_id": "04685f94-1991-5e62-80d2-5669913e99fc"
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
"decision_id": "1ac5a70f-082e-4d8f-9ac8-59e4c175da02",
|
||||
"config": {
|
||||
"ref": "coordination-engine/config/coordination-frame.json",
|
||||
"sha256": "d15e092387f128ffdfd00b9815707a05ff77c5bb0ba4d9a428fbc37b8c440b67",
|
||||
"frame_seconds": 3600,
|
||||
"heartbeat_frames": 1,
|
||||
"registered_wait_frames": 2,
|
||||
"effective_deadline_frames": 3,
|
||||
"decision_id": "1ac5a70f-082e-4d8f-9ac8-59e4c175da02"
|
||||
},
|
||||
"tests": {
|
||||
"coordination_engine": {
|
||||
"passed": 73,
|
||||
"skipped": 1
|
||||
},
|
||||
"coordination_frame_and_profile": {
|
||||
"passed": 32
|
||||
},
|
||||
"approval_engine": {
|
||||
"passed": 271
|
||||
},
|
||||
"qonto_assistant": {
|
||||
"passed": 91
|
||||
},
|
||||
"rapp_qonto": {
|
||||
"passed": 25
|
||||
},
|
||||
"kings_guard": {
|
||||
"passed": 128
|
||||
}
|
||||
},
|
||||
"compiler_check": "no drift",
|
||||
"source_assessments": "source-assessments-f1h.json",
|
||||
"manifest_preservation": "semantic comparison against committed manifests proves only heartbeat settings and frame digest annotations changed; image/identity/secrets/routing/scaling preserved",
|
||||
"deployment_applied": false,
|
||||
"registry_applied": false,
|
||||
"independent_live_observer_proved": false,
|
||||
"source_commits": {
|
||||
"coordination-engine": "f658556690f3f6b7efe9c95a445222019182e402",
|
||||
"approval-engine": "a786b061da4d7730c0827cf4919ab9206aed6d3e",
|
||||
"qonto-assistant": "5eb7e86f7a5fccf8bb8c40bd991e32bb9ae440c9",
|
||||
"rapp-qonto": "51de093b4431fc7cc569be84bc20cbff7aa6a4d5",
|
||||
"kings-guard": "164a4cdaf12e7a450ac225f7a645e769a3e76f40"
|
||||
},
|
||||
"runtime_preflight": "Both timing-only patches passed server dry-run on verified railiance01; nothing applied"
|
||||
}
|
||||
|
|
@ -4,6 +4,99 @@
|
|||
"profile_status": "proposed",
|
||||
"live_observer_proved": false,
|
||||
"source_files": {
|
||||
"approval_source": {
|
||||
"path": "../approval-engine/cadence.yaml",
|
||||
"sha256": "cc58c8d53ebf50acf540d73b7607d579942bda7734c3e8722108e9c9204af655"
|
||||
},
|
||||
"qonto_source": {
|
||||
"path": "../qonto-assistant/specs/audit-emission-cadence.yaml",
|
||||
"sha256": "adedbe06e04c38812057db97364557644157eb5f72f16adebb6f7beec1587005"
|
||||
},
|
||||
"generic_schema": {
|
||||
"path": "../info-tech-canon/infospace/schemas/emission-cadence.schema.yaml",
|
||||
"sha256": "6d52692eb1e4d1325e0d6062d95acded98beddaae5bcfe24c6f0e91f1b6be6ae"
|
||||
},
|
||||
"bearer_revocation_receipt": {
|
||||
"path": "../audit-core/docs/evidence/2026-09-15-sender-bearer-revocation.json",
|
||||
"sha256": "8da798005611711f4a3da969597a3763e6c02e41013df5227b0434dc328b6fb3"
|
||||
},
|
||||
"qonto_historical_capture": {
|
||||
"path": "../rapp-qonto/evidence/live/2026-09-05-audit-rollout.json",
|
||||
"sha256": "1cad71fe93ab2a9f7d5dbc99b9aada47c212a7e43813a86ea91f52639e163be9"
|
||||
}
|
||||
},
|
||||
"approval_engine_registration_proposal": {
|
||||
"status": "not-applied; founder selected configurable f=1h",
|
||||
"sender": "approval-engine",
|
||||
"source": "approval-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"preserve": [
|
||||
"tokens",
|
||||
"secret_policy=redact",
|
||||
"may_write=true",
|
||||
"may_read=false",
|
||||
"existing other senders and registry fields"
|
||||
],
|
||||
"emission_cadence": "Import exact source-owned cadence.yaml at the pinned digest; never use a draft/fallback schema",
|
||||
"class_mapping": {
|
||||
"issuance": "approval.issuance",
|
||||
"use": "approval.use",
|
||||
"supersession": "approval.supersession",
|
||||
"revocation": "approval.revocation",
|
||||
"heartbeat": "audit-core.heartbeat"
|
||||
},
|
||||
"heartbeat_transport": "audit-core.heartbeat",
|
||||
"covered_class_field": "data.class",
|
||||
"source_interval_seconds": 3600,
|
||||
"source_requested_bound_seconds": 7200,
|
||||
"receiver_grace_factor": 1.5,
|
||||
"live_steps": [
|
||||
"Verify generated one-hour frame bindings, current runtime/source pins and separately approved rollout scope",
|
||||
"Review exact protected-registry metadata-only patch preserving credentials and all unrelated entries",
|
||||
"Founder approves exact runtime change; use governed owner custody with contained session and CAS/readback",
|
||||
"Receiver reload under owner change gate; prove actual per-class registration and class-isolated heartbeats",
|
||||
"Emit/drain actual lifecycle transitions under owner-scoped authority; correlate occurrence, acknowledgment and receiver acceptance windows including lag and duplicates",
|
||||
"Independent readback/count comparison and missing-class/lag findings; retain value-safe receipts"
|
||||
],
|
||||
"existing_revocation_proof": "2026-09-15 T1 accepted 202, dropped T1 refused 401, incumbent T0 accepted 202; do not repeat unchanged synthetic proof as if absent",
|
||||
"effective_deadline_seconds": 10800,
|
||||
"coordination_frame": {
|
||||
"ref": "coordination-engine/config/coordination-frame.json",
|
||||
"sha256": "d15e092387f128ffdfd00b9815707a05ff77c5bb0ba4d9a428fbc37b8c440b67",
|
||||
"frame_seconds": 3600,
|
||||
"heartbeat_frames": 1,
|
||||
"registered_wait_frames": 2,
|
||||
"effective_deadline_frames": 3,
|
||||
"decision_id": "1ac5a70f-082e-4d8f-9ac8-59e4c175da02"
|
||||
}
|
||||
},
|
||||
"qonto": {
|
||||
"required_owner": "rapp-qonto",
|
||||
"missing": "Actual stdout collector/sender source/image/config and governed delivery lane",
|
||||
"authoritative_workload_tenant": "tenant:friendly:binky (rapp-qonto binding; collector mapping still needs source/receiver review)",
|
||||
"receiver_commitment": "AUDIT-WP-0013-T05",
|
||||
"receiver_instance_filter": "Implemented in AUDIT-WP-0013-T04; reviewed release and native proof still required",
|
||||
"source_coordination": "QONTO-WP-0006-T02",
|
||||
"observer_acceptance": "KG-WP-0005-T03 then QONTO-WP-0006-T03",
|
||||
"historical_receipt_limit": "Source-path capture with startup and deny; not independent collector/feed acceptance",
|
||||
"source_interval_seconds": 3600,
|
||||
"runtime_status": "source settings prepared; not deployed in this session"
|
||||
},
|
||||
"local_identity": {
|
||||
"status": "explicit incompatibility retained",
|
||||
"expected_findings": [
|
||||
"rare-heartbeat-missing:revoke-token",
|
||||
"rare-heartbeat-missing:serve/token.token_issued"
|
||||
],
|
||||
"completeness_claimed": false
|
||||
},
|
||||
"observer_fix": {
|
||||
"defect": "Shared heartbeat event type could mask silence of another covered class",
|
||||
"change": "Require explicit covered_event_classes as well as matching transport class; retain source/adapter coverage, not inferred traffic/count keys",
|
||||
"old_regression": "False COMPLETE for unscoped audit-core.heartbeat across issuance/revocation",
|
||||
"deployment_or_live_acceptance": false
|
||||
},
|
||||
"source_files_before_frame": {
|
||||
"approval_source": {
|
||||
"path": "../approval-engine/cadence.yaml",
|
||||
"sha256": "0389be492628e2df0d84a70755c92aaf4a749bc64fbf2772e0c3301c3e1fe5ed"
|
||||
|
|
@ -25,73 +118,13 @@
|
|||
"sha256": "1cad71fe93ab2a9f7d5dbc99b9aada47c212a7e43813a86ea91f52639e163be9"
|
||||
}
|
||||
},
|
||||
"approval_engine_registration_proposal": {
|
||||
"status": "not-applied; owner deadline decision pending",
|
||||
"sender": "approval-engine",
|
||||
"source": "approval-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"preserve": [
|
||||
"tokens",
|
||||
"secret_policy=redact",
|
||||
"may_write=true",
|
||||
"may_read=false",
|
||||
"existing other senders and registry fields"
|
||||
],
|
||||
"emission_cadence": "Import exact source-owned cadence.yaml at the pinned digest; never use a draft/fallback schema",
|
||||
"class_mapping": {
|
||||
"issuance": "approval.issuance",
|
||||
"use": "approval.use",
|
||||
"supersession": "approval.supersession",
|
||||
"revocation": "approval.revocation",
|
||||
"heartbeat": "audit-core.heartbeat"
|
||||
},
|
||||
"heartbeat_transport": "audit-core.heartbeat",
|
||||
"covered_class_field": "data.class",
|
||||
"source_interval_seconds": 86400,
|
||||
"source_requested_bound_seconds": 172800,
|
||||
"receiver_grace_factor": 1.5,
|
||||
"deadline_options": [
|
||||
{
|
||||
"effective_seconds": 172800,
|
||||
"registration_seconds": 115200
|
||||
},
|
||||
{
|
||||
"effective_seconds": 259200,
|
||||
"registration_seconds": 172800
|
||||
}
|
||||
],
|
||||
"live_steps": [
|
||||
"Owner confirms effective heartbeat deadline and current runtime/source pin",
|
||||
"Review exact protected-registry metadata-only patch preserving credentials and all unrelated entries",
|
||||
"Founder approves exact runtime change; use governed owner custody with contained session and CAS/readback",
|
||||
"Receiver reload under owner change gate; prove actual per-class registration and class-isolated heartbeats",
|
||||
"Emit/drain actual lifecycle transitions under owner-scoped authority; correlate occurrence, acknowledgment and receiver acceptance windows including lag and duplicates",
|
||||
"Independent readback/count comparison and missing-class/lag findings; retain value-safe receipts"
|
||||
],
|
||||
"existing_revocation_proof": "2026-09-15 T1 accepted 202, dropped T1 refused 401, incumbent T0 accepted 202; do not repeat unchanged synthetic proof as if absent"
|
||||
},
|
||||
"qonto": {
|
||||
"required_owner": "rapp-qonto",
|
||||
"missing": "Actual stdout collector/sender source/image/config and governed delivery lane",
|
||||
"authoritative_workload_tenant": "tenant:friendly:binky (rapp-qonto binding; collector mapping still needs source/receiver review)",
|
||||
"receiver_commitment": "AUDIT-WP-0013-T05",
|
||||
"receiver_instance_filter": "Implemented in AUDIT-WP-0013-T04; reviewed release and native proof still required",
|
||||
"source_coordination": "QONTO-WP-0006-T02",
|
||||
"observer_acceptance": "KG-WP-0005-T03 then QONTO-WP-0006-T03",
|
||||
"historical_receipt_limit": "Source-path capture with startup and deny; not independent collector/feed acceptance"
|
||||
},
|
||||
"local_identity": {
|
||||
"status": "explicit incompatibility retained",
|
||||
"expected_findings": [
|
||||
"rare-heartbeat-missing:revoke-token",
|
||||
"rare-heartbeat-missing:serve/token.token_issued"
|
||||
],
|
||||
"completeness_claimed": false
|
||||
},
|
||||
"observer_fix": {
|
||||
"defect": "Shared heartbeat event type could mask silence of another covered class",
|
||||
"change": "Require explicit covered_event_classes as well as matching transport class; retain source/adapter coverage, not inferred traffic/count keys",
|
||||
"old_regression": "False COMPLETE for unscoped audit-core.heartbeat across issuance/revocation",
|
||||
"deployment_or_live_acceptance": false
|
||||
"coordination_frame": {
|
||||
"ref": "coordination-engine/config/coordination-frame.json",
|
||||
"sha256": "d15e092387f128ffdfd00b9815707a05ff77c5bb0ba4d9a428fbc37b8c440b67",
|
||||
"frame_seconds": 3600,
|
||||
"heartbeat_frames": 1,
|
||||
"registered_wait_frames": 2,
|
||||
"effective_deadline_frames": 3,
|
||||
"decision_id": "1ac5a70f-082e-4d8f-9ac8-59e4c175da02"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
[
|
||||
{
|
||||
"op": "test",
|
||||
"path": "/metadata/uid",
|
||||
"value": "a665e1d0-3ada-4b27-ac56-a8d452499003"
|
||||
},
|
||||
{
|
||||
"op": "test",
|
||||
"path": "/metadata/resourceVersion",
|
||||
"value": "57092911"
|
||||
},
|
||||
{
|
||||
"op": "add",
|
||||
"path": "/spec/template/metadata/annotations/coordination.coulomb.social~1frame-sha256",
|
||||
"value": "d15e092387f128ffdfd00b9815707a05ff77c5bb0ba4d9a428fbc37b8c440b67"
|
||||
},
|
||||
{
|
||||
"op": "replace",
|
||||
"path": "/spec/template/spec/containers/0/env/0/value",
|
||||
"value": "3600"
|
||||
},
|
||||
{
|
||||
"op": "add",
|
||||
"path": "/spec/traffic",
|
||||
"value": [
|
||||
{
|
||||
"revisionName": "rapp-qonto-00009",
|
||||
"percent": 100
|
||||
},
|
||||
{
|
||||
"latestRevision": true,
|
||||
"percent": 0,
|
||||
"tag": "frame-preview"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"approval-engine": {
|
||||
"patch": "approval-engine-frame-runtime-patch.json",
|
||||
"server_dry_run_exit": 0,
|
||||
"resource_uid": "8b44c901-024f-4472-a822-2fd07aa2be5f",
|
||||
"resource_version": "75292270",
|
||||
"additional_owner_step": "OnDelete requires separately approved controlled restart of approval-engine-0; image and storage schema stay unchanged",
|
||||
"live_mutations": false
|
||||
},
|
||||
"rapp-qonto": {
|
||||
"patch": "rapp-qonto-frame-runtime-patch.json",
|
||||
"server_dry_run_exit": 0,
|
||||
"resource_uid": "a665e1d0-3ada-4b27-ac56-a8d452499003",
|
||||
"resource_version": "57092911",
|
||||
"additional_owner_step": "Keep all traffic on the current Ready revision while creating zero-percent frame-preview candidate; promote only after owner verification",
|
||||
"live_mutations": false
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"live_mutations": false,
|
||||
"cluster_uid": "a553c742-0115-43d4-99a4-a5ca56fe0786",
|
||||
"resources": {
|
||||
"approval-engine": {
|
||||
"available": true,
|
||||
"kind": "statefulset",
|
||||
"namespace": "approval-engine",
|
||||
"uid": "8b44c901-024f-4472-a822-2fd07aa2be5f",
|
||||
"resource_version": "75292270",
|
||||
"image": "forgejo.coulomb.social/coulomb/approval-engine@sha256:251941a5cb2724b57cc32cff6b693b1ab0be695bee4f56f02d51961189c0fa49",
|
||||
"heartbeat_argument_seconds": [],
|
||||
"heartbeat_environment_seconds": [],
|
||||
"frame_digest": null,
|
||||
"status_ready": 1,
|
||||
"rollout_strategy": "OnDelete"
|
||||
},
|
||||
"rapp-qonto": {
|
||||
"available": true,
|
||||
"kind": "ksvc",
|
||||
"namespace": "rapp-qonto",
|
||||
"uid": "a665e1d0-3ada-4b27-ac56-a8d452499003",
|
||||
"resource_version": "57092911",
|
||||
"image": "forgejo.coulomb.social/coulomb/rapp-qonto@sha256:2e42b5e665a19ffa3b3ae8109a8aab64f5485329f72810be063263ff5086cb3f",
|
||||
"heartbeat_argument_seconds": [],
|
||||
"heartbeat_environment_seconds": [
|
||||
"86400"
|
||||
],
|
||||
"frame_digest": null,
|
||||
"status_ready": "rapp-qonto-00009",
|
||||
"rollout_strategy": null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
{
|
||||
"live_observer_proved": false,
|
||||
"reports": {
|
||||
"approval-engine": {
|
||||
"assessment_scope": "supplied-inventory",
|
||||
"conformant": true,
|
||||
"contract_schema": "../info-tech-canon/infospace/schemas/emission-cadence.schema.yaml",
|
||||
"contract_valid": true,
|
||||
"declaration": "../approval-engine/cadence.yaml",
|
||||
"findings": [],
|
||||
"inventory": {
|
||||
"attributive": [],
|
||||
"load_bearing": [
|
||||
"heartbeat"
|
||||
],
|
||||
"rare_load_bearing": [
|
||||
"issuance",
|
||||
"revocation",
|
||||
"supersession",
|
||||
"use"
|
||||
]
|
||||
},
|
||||
"profile": "netkingdom-emission-cadence-security-profile-v0.1",
|
||||
"profile_assessed": true,
|
||||
"summary": {
|
||||
"must": 0,
|
||||
"should": 0
|
||||
}
|
||||
},
|
||||
"local-identity": {
|
||||
"assessment_scope": "supplied-inventory",
|
||||
"conformant": false,
|
||||
"contract_schema": "../info-tech-canon/infospace/schemas/emission-cadence.schema.yaml",
|
||||
"contract_valid": true,
|
||||
"declaration": "local-identity/emission-cadence.yaml",
|
||||
"findings": [
|
||||
{
|
||||
"code": "rare-heartbeat-missing",
|
||||
"event_class": "revoke-token",
|
||||
"level": "MUST",
|
||||
"message": "rare load-bearing evidence requires a positive heartbeat"
|
||||
},
|
||||
{
|
||||
"code": "rare-heartbeat-missing",
|
||||
"event_class": "serve/token.token_issued",
|
||||
"level": "MUST",
|
||||
"message": "rare load-bearing evidence requires a positive heartbeat"
|
||||
}
|
||||
],
|
||||
"inventory": {
|
||||
"attributive": [],
|
||||
"load_bearing": [],
|
||||
"rare_load_bearing": [
|
||||
"revoke-token",
|
||||
"serve/token.token_issued"
|
||||
]
|
||||
},
|
||||
"profile": "netkingdom-emission-cadence-security-profile-v0.1",
|
||||
"profile_assessed": true,
|
||||
"summary": {
|
||||
"must": 2,
|
||||
"should": 0
|
||||
}
|
||||
},
|
||||
"qonto-assistant": {
|
||||
"assessment_scope": "supplied-inventory",
|
||||
"conformant": true,
|
||||
"contract_schema": "../info-tech-canon/infospace/schemas/emission-cadence.schema.yaml",
|
||||
"contract_valid": true,
|
||||
"declaration": "../qonto-assistant/specs/audit-emission-cadence.yaml",
|
||||
"findings": [],
|
||||
"inventory": {
|
||||
"attributive": [
|
||||
"audit.allow"
|
||||
],
|
||||
"load_bearing": [
|
||||
"audit.deny",
|
||||
"audit.heartbeat"
|
||||
],
|
||||
"rare_load_bearing": [
|
||||
"audit.deny"
|
||||
]
|
||||
},
|
||||
"profile": "netkingdom-emission-cadence-security-profile-v0.1",
|
||||
"profile_assessed": true,
|
||||
"summary": {
|
||||
"must": 0,
|
||||
"should": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
26
generated/coordination-frame/approval-engine-receiver.json
Normal file
26
generated/coordination-frame/approval-engine-receiver.json
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"status": "proposed-not-applied",
|
||||
"coordination_frame": {
|
||||
"ref": "coordination-engine/config/coordination-frame.json",
|
||||
"sha256": "d15e092387f128ffdfd00b9815707a05ff77c5bb0ba4d9a428fbc37b8c440b67",
|
||||
"frame_seconds": 3600,
|
||||
"heartbeat_frames": 1,
|
||||
"registered_wait_frames": 2,
|
||||
"effective_deadline_frames": 3
|
||||
},
|
||||
"sender": "approval-engine",
|
||||
"source": "approval-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"may_read": false,
|
||||
"emission_cadence_ref": "approval-engine/cadence.yaml",
|
||||
"emission_cadence_sha256": "cc58c8d53ebf50acf540d73b7607d579942bda7734c3e8722108e9c9204af655",
|
||||
"heartbeat_classes": {
|
||||
"issuance": 7200,
|
||||
"use": 7200,
|
||||
"supersession": 7200,
|
||||
"revocation": 7200
|
||||
},
|
||||
"receiver_grace_factor": 1.5,
|
||||
"effective_deadline_seconds": 10800,
|
||||
"preserve_existing_credentials_and_other_registry_fields": true
|
||||
}
|
||||
42
tools/coordination-frame/README.md
Normal file
42
tools/coordination-frame/README.md
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# Coordination-frame bindings
|
||||
|
||||
The ecosystem frame is owned by coordination-engine at
|
||||
`coordination-engine/config/coordination-frame.json`. Its initial value is
|
||||
`frame_seconds: 3600`, selected by the founder on 2026-10-15. Change that one
|
||||
setting to change the pace. The owner API validates positive integer frames
|
||||
and derives timezone-bound deadlines; this tool imports that API, with no
|
||||
fallback config or duplicated reader.
|
||||
|
||||
For cadence adoption the formulas are heartbeat **f**, registered receiver
|
||||
wait **2f**, and effective missing-heartbeat deadline **3f** after Audit Core's
|
||||
existing 1.5 grace. At f=1h those are 3600, 7200 and 10800 seconds. A return
|
||||
to f=24h produces 24h/48h/72h through the same formulas.
|
||||
|
||||
From net-kingdom:
|
||||
|
||||
```sh
|
||||
python3 tools/coordination-frame/render.py # read-only source plan
|
||||
python3 tools/coordination-frame/render.py --check # fail on derived-file drift
|
||||
python3 tools/coordination-frame/render.py --write # regenerate source artifacts
|
||||
python3 -m pytest -q tools/coordination-frame/tests
|
||||
```
|
||||
|
||||
`--write` changes only the listed source files. It prepares Approval Engine
|
||||
and Qonto declarations, generated Python defaults, both deployment heartbeat
|
||||
settings, and a non-secret proposed Approval Engine receiver registration.
|
||||
The compiler preserves image pins, identity, secret references, other source
|
||||
classifications and the lack of a completeness claim. Each generated consumer
|
||||
records the frame source and SHA-256. Runtime consumers import their generated
|
||||
values rather than opening an adjacent coordination-engine checkout.
|
||||
|
||||
Check generated artifacts after changing the frame, review/commit each owner
|
||||
source, then use the owner's approved release and registry procedures. This
|
||||
tool performs no login, credential operation, registry update or deployment.
|
||||
It cannot replace a source collector or provide operational observer evidence.
|
||||
All five binding tests require the sibling owner checkouts and explicitly skip
|
||||
when they are unavailable; no substitute owner contract is used.
|
||||
|
||||
This is the first rollout of a shared coordination setting. Other ecosystem
|
||||
coordination consumers must adopt explicit frame multipliers through their own
|
||||
configuration. Transport polling, security validity and credential leases are
|
||||
not silently rescaled by a coordination setting.
|
||||
214
tools/coordination-frame/render.py
Normal file
214
tools/coordination-frame/render.py
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Compile owner-reviewed cadence bindings from the ecosystem coordination frame."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
FRAME_REF = "coordination-engine/config/coordination-frame.json"
|
||||
|
||||
|
||||
def owner_frame(workspace: Path):
|
||||
source = workspace / "coordination-engine/src/coordination_engine/timing.py"
|
||||
spec = importlib.util.spec_from_file_location("coordination_frame_owner", source)
|
||||
if spec is None or spec.loader is None:
|
||||
raise ValueError("coordination-engine frame API is required; no fallback")
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
sys.modules[spec.name] = module
|
||||
spec.loader.exec_module(module)
|
||||
return module.load_frame(workspace / FRAME_REF)
|
||||
|
||||
|
||||
def generated_module(frame, digest):
|
||||
return (
|
||||
'"""Generated cadence timings; regenerate with NetKingdom coordination-frame tool."""\n'
|
||||
f"# Source: {FRAME_REF}\n"
|
||||
f'FRAME_CONFIG_SHA256 = "{digest}"\n'
|
||||
f"FRAME_SECONDS = {frame.frame_seconds}\n"
|
||||
f"RECEIVER_WAIT_SECONDS = {frame.seconds(2)}\n"
|
||||
f"EFFECTIVE_DEADLINE_SECONDS = {frame.seconds(3)}\n"
|
||||
)
|
||||
|
||||
|
||||
def bind_frame_annotation(text, digest, metadata_prefix):
|
||||
key = "coordination.coulomb.social/frame-sha256"
|
||||
pattern = r"(?m)^(\s*" + re.escape(key) + r": )[^\n]+"
|
||||
if re.search(pattern, text):
|
||||
updated, count = re.subn(pattern, lambda match: match[1] + json.dumps(digest), text)
|
||||
else:
|
||||
replacement = (
|
||||
metadata_prefix
|
||||
+ "annotations:\n"
|
||||
+ " " * (len(metadata_prefix.splitlines()[-1]) + 2)
|
||||
+ key
|
||||
+ ": "
|
||||
+ json.dumps(digest)
|
||||
+ "\n"
|
||||
)
|
||||
# metadata_prefix ends with the indentation for annotations. Existing
|
||||
# annotation maps retain their contents; otherwise insert a new map.
|
||||
if metadata_prefix + "annotations:\n" in text:
|
||||
updated = text.replace(metadata_prefix + "annotations:\n", replacement, 1)
|
||||
count = 1
|
||||
else:
|
||||
updated = text.replace(
|
||||
metadata_prefix, replacement + metadata_prefix.rsplit("\n", 1)[-1], 1
|
||||
)
|
||||
count = int(updated != text)
|
||||
if count != 1:
|
||||
raise ValueError("expected one runtime frame provenance binding")
|
||||
return updated
|
||||
|
||||
|
||||
def compile_bindings(workspace: Path):
|
||||
frame = owner_frame(workspace)
|
||||
digest = hashlib.sha256((workspace / FRAME_REF).read_bytes()).hexdigest()
|
||||
provenance = {
|
||||
"ref": FRAME_REF,
|
||||
"sha256": digest,
|
||||
"frame_seconds": frame.frame_seconds,
|
||||
"heartbeat_frames": 1,
|
||||
"registered_wait_frames": 2,
|
||||
"effective_deadline_frames": 3,
|
||||
}
|
||||
outputs = {}
|
||||
for relative in (
|
||||
"approval-engine/approval_engine/coordination.py",
|
||||
"qonto-assistant/src/qonto_assistant/coordination.py",
|
||||
):
|
||||
outputs[workspace / relative] = generated_module(frame, digest)
|
||||
approval_path = workspace / "approval-engine/cadence.yaml"
|
||||
approval = json.loads(approval_path.read_text())
|
||||
for entry in approval["sources"]:
|
||||
if "heartbeat" in entry:
|
||||
beat = entry["heartbeat"]
|
||||
beat["interval_seconds"] = frame.frame_seconds
|
||||
ext = beat["extensions"]["approval-engine"]
|
||||
ext["requested_observer_max_gap_seconds"] = frame.seconds(2)
|
||||
ext["effective_deadline_seconds"] = frame.seconds(3)
|
||||
approval["extensions"].setdefault("netkingdom", {})["coordination_frame"] = provenance
|
||||
outputs[approval_path] = json.dumps(approval, indent=2) + "\n"
|
||||
|
||||
qonto_path = workspace / "qonto-assistant/specs/audit-emission-cadence.yaml"
|
||||
qonto = yaml.safe_load(qonto_path.read_text())
|
||||
for entry in qonto["sources"]:
|
||||
if "heartbeat" in entry:
|
||||
entry["heartbeat"]["interval"] = f"PT{frame.frame_seconds}S"
|
||||
heartbeat = qonto["extensions"]["qonto-assistant"]["heartbeat"]
|
||||
heartbeat["interval"] = f"PT{frame.frame_seconds}S"
|
||||
heartbeat["default_interval_seconds"] = frame.frame_seconds
|
||||
qonto["extensions"]["netkingdom"]["coordination_frame"] = provenance
|
||||
outputs[qonto_path] = (
|
||||
"# Source-owned cadence; coordination timings generated from "
|
||||
+ FRAME_REF
|
||||
+ "\n"
|
||||
+ yaml.safe_dump(qonto, sort_keys=False)
|
||||
)
|
||||
|
||||
deploy_path = workspace / "approval-engine/deploy/approval-engine.yaml"
|
||||
deploy = deploy_path.read_text()
|
||||
if re.search(r"^\s+- --heartbeat-seconds\s*$", deploy, re.M):
|
||||
deploy, count = re.subn(
|
||||
r"(?m)^(\s+- --heartbeat-seconds\n\s+- )[^\n]+",
|
||||
lambda m: m[1] + json.dumps(str(frame.frame_seconds)),
|
||||
deploy,
|
||||
)
|
||||
else:
|
||||
# Explicit runtime arg also works with the already pinned image; no image
|
||||
# pin, storage migration, authority or unrelated deployment change here.
|
||||
deploy, count = re.subn(
|
||||
r"(?m)^(\s+)- --audit-url$",
|
||||
lambda m: (
|
||||
f'{m[1]}- --heartbeat-seconds\n{m[1]}- "{frame.frame_seconds}"\n{m[1]}- --audit-url'
|
||||
),
|
||||
deploy,
|
||||
)
|
||||
if count != 1:
|
||||
raise ValueError("expected one Approval Engine heartbeat argument binding")
|
||||
outputs[deploy_path] = bind_frame_annotation(
|
||||
deploy, digest, " template:\n metadata:\n "
|
||||
)
|
||||
|
||||
deploy_path = workspace / "rapp-qonto/runtime/knative/service.yaml"
|
||||
deploy, count = re.subn(
|
||||
r"(?m)(name: QONTO_AUDIT_HEARTBEAT_INTERVAL_SECONDS\n\s+value: )[^\n]+",
|
||||
lambda m: m[1] + json.dumps(str(frame.frame_seconds)),
|
||||
deploy_path.read_text(),
|
||||
)
|
||||
if count != 1:
|
||||
raise ValueError("expected one Qonto heartbeat environment binding")
|
||||
outputs[deploy_path] = bind_frame_annotation(
|
||||
deploy, digest, " template:\n metadata:\n "
|
||||
)
|
||||
|
||||
fixture_path = (
|
||||
workspace / "kings-guard/src/kings_guard/fixtures/qonto_assistant_source_cadence.json"
|
||||
)
|
||||
fixture = json.loads(fixture_path.read_text())
|
||||
for entry in fixture["sources"]:
|
||||
if "heartbeat" in entry:
|
||||
entry["heartbeat"]["interval_seconds"] = frame.frame_seconds
|
||||
fixture["extensions"].setdefault("netkingdom", {})["coordination_frame"] = provenance
|
||||
outputs[fixture_path] = json.dumps(fixture, indent=2) + "\n"
|
||||
|
||||
receiver = {
|
||||
"status": "proposed-not-applied",
|
||||
"coordination_frame": provenance,
|
||||
"sender": "approval-engine",
|
||||
"source": "approval-engine",
|
||||
"tenant": "tenant:platform",
|
||||
"may_read": False,
|
||||
"emission_cadence_ref": "approval-engine/cadence.yaml",
|
||||
"emission_cadence_sha256": hashlib.sha256(outputs[approval_path].encode()).hexdigest(),
|
||||
"heartbeat_classes": {
|
||||
name: frame.seconds(2) for name in ("issuance", "use", "supersession", "revocation")
|
||||
},
|
||||
"receiver_grace_factor": 1.5,
|
||||
"effective_deadline_seconds": frame.seconds(3),
|
||||
"preserve_existing_credentials_and_other_registry_fields": True,
|
||||
}
|
||||
outputs[
|
||||
workspace / "net-kingdom/generated/coordination-frame/approval-engine-receiver.json"
|
||||
] = json.dumps(receiver, indent=2) + "\n"
|
||||
return frame, outputs
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--workspace", type=Path, default=ROOT.parent)
|
||||
mode = parser.add_mutually_exclusive_group()
|
||||
mode.add_argument("--check", action="store_true")
|
||||
mode.add_argument("--write", action="store_true")
|
||||
args = parser.parse_args(argv)
|
||||
try:
|
||||
frame, outputs = compile_bindings(args.workspace)
|
||||
changed = {
|
||||
p: text for p, text in outputs.items() if not p.exists() or p.read_text() != text
|
||||
}
|
||||
if args.write:
|
||||
for path, text in changed.items():
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(text)
|
||||
report = {
|
||||
"frame": frame.as_dict(),
|
||||
"mode": "write" if args.write else "check" if args.check else "plan",
|
||||
"changed": [str(p.relative_to(args.workspace)) for p in changed],
|
||||
"live_operations": False,
|
||||
}
|
||||
print(json.dumps(report, indent=2, sort_keys=True))
|
||||
return 1 if args.check and changed else 0
|
||||
except (OSError, ValueError, KeyError, TypeError) as exc:
|
||||
parser.error(str(exc))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
127
tools/coordination-frame/tests/test_render.py
Normal file
127
tools/coordination-frame/tests/test_render.py
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
import yaml
|
||||
|
||||
SCRIPT = Path(__file__).resolve().parents[1] / "render.py"
|
||||
SPEC = importlib.util.spec_from_file_location("frame_renderer", SCRIPT)
|
||||
renderer = importlib.util.module_from_spec(SPEC)
|
||||
SPEC.loader.exec_module(renderer)
|
||||
WORKSPACE = SCRIPT.parents[3]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def workspace(tmp_path):
|
||||
required = (
|
||||
"coordination-engine/config/coordination-frame.json",
|
||||
"coordination-engine/src/coordination_engine/timing.py",
|
||||
"approval-engine/cadence.yaml",
|
||||
"approval-engine/deploy/approval-engine.yaml",
|
||||
"qonto-assistant/specs/audit-emission-cadence.yaml",
|
||||
"rapp-qonto/runtime/knative/service.yaml",
|
||||
"kings-guard/src/kings_guard/fixtures/qonto_assistant_source_cadence.json",
|
||||
)
|
||||
if any(not (WORKSPACE / name).is_file() for name in required):
|
||||
pytest.skip("sibling owner sources required; no fallback frame or contract")
|
||||
for name in (
|
||||
"coordination-engine/config/coordination-frame.json",
|
||||
"coordination-engine/src/coordination_engine/timing.py",
|
||||
"approval-engine/cadence.yaml",
|
||||
"approval-engine/deploy/approval-engine.yaml",
|
||||
"qonto-assistant/specs/audit-emission-cadence.yaml",
|
||||
"rapp-qonto/runtime/knative/service.yaml",
|
||||
"kings-guard/src/kings_guard/fixtures/qonto_assistant_source_cadence.json",
|
||||
):
|
||||
path = tmp_path / name
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copyfile(WORKSPACE / name, path)
|
||||
return tmp_path
|
||||
|
||||
|
||||
@pytest.mark.parametrize("frame_seconds", [600, 3600, 86400])
|
||||
def test_one_frame_edit_rescales_sources_runtime_and_receiver(workspace, frame_seconds):
|
||||
config = workspace / renderer.FRAME_REF
|
||||
config.write_text(
|
||||
json.dumps({"schema_version": "coordination-frame/v1", "frame_seconds": frame_seconds})
|
||||
)
|
||||
_, outputs = renderer.compile_bindings(workspace)
|
||||
approval = json.loads(outputs[workspace / "approval-engine/cadence.yaml"])
|
||||
qonto = yaml.safe_load(outputs[workspace / "qonto-assistant/specs/audit-emission-cadence.yaml"])
|
||||
for entry in approval["sources"]:
|
||||
if "heartbeat" in entry:
|
||||
assert entry["heartbeat"]["interval_seconds"] == frame_seconds
|
||||
extension = entry["heartbeat"]["extensions"]["approval-engine"]
|
||||
assert extension["requested_observer_max_gap_seconds"] == 2 * frame_seconds
|
||||
assert extension["effective_deadline_seconds"] == 3 * frame_seconds
|
||||
for entry in qonto["sources"]:
|
||||
assert entry["heartbeat"]["interval"] == f"PT{frame_seconds}S"
|
||||
observer = json.loads(
|
||||
outputs[
|
||||
workspace / "kings-guard/src/kings_guard/fixtures/qonto_assistant_source_cadence.json"
|
||||
]
|
||||
)
|
||||
assert observer["sources"][0]["heartbeat"]["interval_seconds"] == frame_seconds
|
||||
|
||||
receiver = json.loads(
|
||||
outputs[
|
||||
workspace / "net-kingdom/generated/coordination-frame/approval-engine-receiver.json"
|
||||
]
|
||||
)
|
||||
assert set(receiver["heartbeat_classes"].values()) == {2 * frame_seconds}
|
||||
assert receiver["effective_deadline_seconds"] == 3 * frame_seconds
|
||||
assert receiver["may_read"] is False
|
||||
assert receiver["status"] == "proposed-not-applied"
|
||||
for name in (
|
||||
"approval-engine/approval_engine/coordination.py",
|
||||
"qonto-assistant/src/qonto_assistant/coordination.py",
|
||||
):
|
||||
assert f"FRAME_SECONDS = {frame_seconds}\n" in outputs[workspace / name]
|
||||
deploy = yaml.safe_load_all(outputs[workspace / "approval-engine/deploy/approval-engine.yaml"])
|
||||
workload = next(item for item in deploy if item["kind"] == "StatefulSet")
|
||||
expected_digest = hashlib.sha256(config.read_bytes()).hexdigest()
|
||||
assert (
|
||||
workload["spec"]["template"]["metadata"]["annotations"][
|
||||
"coordination.coulomb.social/frame-sha256"
|
||||
]
|
||||
== expected_digest
|
||||
)
|
||||
args = workload["spec"]["template"]["spec"]["containers"][0]["args"]
|
||||
assert args[args.index("--heartbeat-seconds") + 1] == str(frame_seconds)
|
||||
service = yaml.safe_load(outputs[workspace / "rapp-qonto/runtime/knative/service.yaml"])
|
||||
assert (
|
||||
service["spec"]["template"]["metadata"]["annotations"][
|
||||
"coordination.coulomb.social/frame-sha256"
|
||||
]
|
||||
== expected_digest
|
||||
)
|
||||
env = service["spec"]["template"]["spec"]["containers"][0]["env"]
|
||||
assert next(
|
||||
item["value"] for item in env if item["name"] == "QONTO_AUDIT_HEARTBEAT_INTERVAL_SECONDS"
|
||||
) == str(frame_seconds)
|
||||
|
||||
|
||||
def test_render_is_read_only_and_write_is_idempotent_with_drift_detection(workspace, capsys):
|
||||
before = {path: path.read_bytes() for path in workspace.rglob("*") if path.is_file()}
|
||||
assert renderer.main(["--workspace", str(workspace)]) == 0
|
||||
assert all(path.read_bytes() == data for path, data in before.items())
|
||||
assert renderer.main(["--workspace", str(workspace), "--check"]) == 1
|
||||
assert renderer.main(["--workspace", str(workspace), "--write"]) == 0
|
||||
assert renderer.main(["--workspace", str(workspace), "--check"]) == 0
|
||||
receiver = workspace / "net-kingdom/generated/coordination-frame/approval-engine-receiver.json"
|
||||
data = json.loads(receiver.read_text())
|
||||
data["heartbeat_classes"]["revocation"] = 999999
|
||||
receiver.write_text(json.dumps(data))
|
||||
assert renderer.main(["--workspace", str(workspace), "--check"]) == 1
|
||||
|
||||
|
||||
def test_invalid_frame_does_not_partially_rewrite_sources(workspace):
|
||||
config = workspace / renderer.FRAME_REF
|
||||
config.write_text('{"schema_version":"coordination-frame/v1","frame_seconds":0}')
|
||||
before = {path: path.read_bytes() for path in workspace.rglob("*") if path.is_file()}
|
||||
with pytest.raises(SystemExit):
|
||||
renderer.main(["--workspace", str(workspace), "--write"])
|
||||
assert all(path.read_bytes() == data for path, data in before.items())
|
||||
|
|
@ -5,7 +5,7 @@ title: "Publish the NetKingdom emission-cadence security profile"
|
|||
domain: infotech
|
||||
repo: net-kingdom
|
||||
status: blocked
|
||||
flavor: residual
|
||||
flavor: implementation
|
||||
owner: codex
|
||||
topic_slug: netkingdom
|
||||
planning_priority: P1
|
||||
|
|
@ -90,7 +90,7 @@ Python compilation and `git diff --check` pass.
|
|||
id: NK-WP-0035-T04
|
||||
status: wait
|
||||
blocked_on: message-from:approval-engine
|
||||
blocking_reason: "Approval Engine effective heartbeat deadline needs owner choice (48h requested; receiver applies 1.5 grace), followed by approved cadence registry/runtime acceptance and lifecycle reconciliation. Qonto needs an actual rapp-qonto collector and AUDIT-WP-0013-T05 sender admission before KG-WP-0005-T03 operational observation. Existing bearer-revocation proof is delivered; local-identity incompatibility remains explicit."
|
||||
blocking_reason: "Founder chose configurable frame f=1h: source heartbeat f, receiver wait 2f, effective deadline 3f. Generated source/runtime bindings await approved deployment and registry admission plus actual lifecycle reconciliation. Qonto still needs an actual rapp-qonto collector and AUDIT-WP-0013-T05 sender admission before KG-WP-0005-T03 observation. Existing bearer-revocation proof is delivered; local-identity incompatibility remains explicit."
|
||||
priority: high
|
||||
state_hub_task_id: "e3fbc8b8-00d5-57ce-ba0c-19b58044c950"
|
||||
```
|
||||
|
|
@ -276,3 +276,47 @@ Knowledge: Emergent 0.2.6, digest
|
|||
`8d1d6a9d4d07fec7b619618de7dfe2be2254c1790f85f4198c7fe19db9751c02`;
|
||||
start/evidence source guidance directly reviewed, withheld/orientation-only
|
||||
receipt retained. This supplies no operational authority.
|
||||
|
||||
|
||||
## Introduce a configurable ecosystem coordination frame
|
||||
|
||||
```task
|
||||
id: NK-WP-0035-T06
|
||||
status: done
|
||||
priority: high
|
||||
```
|
||||
|
||||
Founder direction in this sitting supersedes the binary 48h/72h question:
|
||||
long-term ecosystem coordination uses one configurable base frame, initially
|
||||
**f=1h**, with waits of **2f** and **3f**. Decision:
|
||||
`1ac5a70f-082e-4d8f-9ac8-59e4c175da02`.
|
||||
|
||||
Authoritative config is `coordination-engine/config/coordination-frame.json`.
|
||||
The coordination-engine API validates it and derives durations / deadlines.
|
||||
NetKingdom's compiler derives source declarations, consumer Python defaults,
|
||||
Approval Engine's deployment heartbeat argument, Qonto's deployment environment
|
||||
setting, and the proposed receiver metadata, retaining the frame digest.
|
||||
Heartbeat is f=3600s; registered wait is 2f=7200s; the receiver's 1.5 grace
|
||||
makes the effective deadline 3f=10800s. The formulas also reproduce the old
|
||||
24h/48h/72h cadence when f is set to 24h.
|
||||
|
||||
This is source-level adoption of the setting, not proof that the deployed
|
||||
processes have changed pace or that every ecosystem timer has adopted it.
|
||||
Runtime release/registry receipts remain T04. Credential and approval validity,
|
||||
worker leases and transport retry timers are separate owner contracts.
|
||||
[Configuration and regeneration](../tools/coordination-frame/README.md).
|
||||
|
||||
|
||||
T06 source acceptance: **73 coordination-engine tests passed, one live test
|
||||
skipped; 32 compiler/profile tests; 271 Approval Engine; 91 Qonto; 25 package;
|
||||
128 King's Guard tests passed**. The compiler's --check has no drift. Changing
|
||||
f to 10 minutes or 24 hours in isolated test workspaces rescales source,
|
||||
receiver and observer bindings together. Prepared manifests preserve image,
|
||||
identity, secret, routing and scaling fields apart from the timing values and
|
||||
frame-digest annotations. [Frame validation](../docs/evidence/2026-10-15-cadence-adoption/coordination-frame-validation.json).
|
||||
|
||||
The earlier 48h/72h question is resolved by the explicit configurable-frame
|
||||
decision. No further deadline selection is waiting on the founder. T04 still
|
||||
requires actual approved rollout/registration, missing Qonto collector/admission,
|
||||
and operational lifecycle/observer acceptance. The profile remains proposed;
|
||||
this workplan is now **5/6 source tasks done**, with T04's operational gate open.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue