rcf-lite 0.24.0 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/blueprints/application-account-settings/docs/topics.md +4 -1
- package/blueprints/application-admin-console/docs/topics.md +4 -1
- package/blueprints/application-api-rest/docs/topics.md +4 -1
- package/blueprints/application-charts/docs/topics.md +4 -1
- package/blueprints/application-dashboard/docs/topics.md +4 -1
- package/blueprints/application-datatable/docs/topics.md +4 -1
- package/blueprints/application-empty-error-states/docs/topics.md +4 -1
- package/blueprints/application-error-handling/docs/topics.md +4 -1
- package/blueprints/application-file-upload/docs/topics.md +4 -1
- package/blueprints/application-forms-wizard/docs/topics.md +4 -1
- package/blueprints/application-notifications-in-app/docs/topics.md +4 -1
- package/blueprints/application-onboarding-tour/docs/topics.md +4 -1
- package/blueprints/application-spa/docs/topics.md +4 -1
- package/blueprints/delivery-ci-workflows/docs/topics.md +4 -1
- package/blueprints/deploy-cloudflare-workers/docs/topics.md +4 -1
- package/blueprints/deploy-hetzner-server/CHANGELOG.md +55 -0
- package/blueprints/deploy-hetzner-server/README.md +202 -0
- package/blueprints/deploy-hetzner-server/blueprint.json +233 -0
- package/blueprints/deploy-hetzner-server/contributions/adrs/adr-3801-deploy-hetzner-server-cloud-host-contract.json +14 -0
- package/blueprints/deploy-hetzner-server/contributions/adrs/adr-3802-deploy-hetzner-server-snapshot-cadence.json +14 -0
- package/blueprints/deploy-hetzner-server/contributions/adrs/adr-3803-deploy-hetzner-server-provisioning-tool.json +20 -0
- package/blueprints/deploy-hetzner-server/contributions/adrs/adr-3804-deploy-hetzner-server-hardening-baseline.json +14 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/cloud-init-render-lint.mjs +71 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/hcloud-dry-run-mock.mjs +164 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/manifest-schema-validate.mjs +182 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/probe-utils.mjs +112 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/real-account-cloud-init-hardened.mjs +64 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/real-account-snapshot-on-demand.mjs +60 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/real-account-throwaway-server-provision.mjs +58 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/run-cloud-init-render-lint.mjs +9 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/run-hcloud-dry-run-mock.mjs +9 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/run-manifest-schema-validate.mjs +9 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/run-real-account-cloud-init-hardened.mjs +9 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/run-real-account-snapshot-on-demand.mjs +9 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/run-real-account-throwaway-server-provision.mjs +9 -0
- package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-001.json +18 -0
- package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-002.json +18 -0
- package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-003.json +18 -0
- package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-004.json +18 -0
- package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-005.json +18 -0
- package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-006.json +18 -0
- package/blueprints/deploy-hetzner-server/contributions/schemas/hetzner-server.schema.json +108 -0
- package/blueprints/deploy-hetzner-server/contributions/tacs/tac-3801-deploy-hetzner-server-provisioner.json +27 -0
- package/blueprints/deploy-hetzner-server/contributions/tacs/tac-3802-deploy-hetzner-server-manifest-schema.json +26 -0
- package/blueprints/deploy-hetzner-server/contributions/tacs/tac-3803-deploy-hetzner-server-cloud-init-template.json +26 -0
- package/blueprints/deploy-hetzner-server/contributions/tacs/tac-3804-deploy-hetzner-server-firewall-shape.json +25 -0
- package/blueprints/deploy-hetzner-server/contributions/templates/cloud-init.yaml.tmpl +113 -0
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37101.json +24 -0
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37102.json +24 -0
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37103.json +25 -0
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37104.json +24 -0
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37105.json +24 -0
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37106.json +25 -0
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37107.json +24 -0
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37108.json +24 -0
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37109.json +24 -0
- package/blueprints/deploy-hetzner-server/docs/topics.md +48 -0
- package/blueprints/deploy-hetzner-server/guide/deploy-hetzner-server.md +180 -0
- package/blueprints/edge-cloudflare-access/docs/topics.md +4 -1
- package/blueprints/edge-cloudflare-rate-limiting/docs/topics.md +4 -1
- package/blueprints/edge-cloudflare-tunnel/CHANGELOG.md +23 -0
- package/blueprints/edge-cloudflare-tunnel/README.md +257 -0
- package/blueprints/edge-cloudflare-tunnel/blueprint.json +168 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/adrs/adr-4001-edge-cloudflare-tunnel-ingress-bridge-contract.json +23 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/adrs/adr-4002-edge-cloudflare-tunnel-connector-runtime.json +19 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/adrs/adr-4003-edge-cloudflare-tunnel-hostname-mode.json +19 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/probes/aud-presence-check.mjs +114 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/probes/cloudflared-config-lint.mjs +80 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/probes/manifest-schema-validate.mjs +237 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/probes/probe-utils.mjs +231 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/probes/real-account-connector-healthy.mjs +143 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/probes/real-account-tunnel-hostname-routes.mjs +166 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/probes/run-aud-presence-check.mjs +4 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/probes/run-cloudflared-config-lint.mjs +4 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/probes/run-manifest-schema-validate.mjs +4 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/probes/run-real-account-connector-healthy.mjs +4 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/probes/run-real-account-tunnel-hostname-routes.mjs +4 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/probes/tunnel-manifest.schema.json +55 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-001.json +18 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-002.json +18 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-003.json +18 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-004.json +18 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-005.json +18 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/tacs/tac-4001-edge-cloudflare-tunnel-connector-shape.json +26 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/tacs/tac-4002-edge-cloudflare-tunnel-manifest-schema.json +26 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/tacs/tac-4003-edge-cloudflare-tunnel-access-binding.json +25 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39101.json +24 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39102.json +24 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39103.json +24 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39104.json +24 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39105.json +24 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39106.json +24 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39107.json +24 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39108.json +24 -0
- package/blueprints/edge-cloudflare-tunnel/docs/topics.md +72 -0
- package/blueprints/edge-cloudflare-tunnel/guide/edge-cloudflare-tunnel.md +204 -0
- package/blueprints/edge-cloudflare-turnstile/docs/topics.md +4 -1
- package/blueprints/email-smtp-resend/docs/topics.md +4 -1
- package/blueprints/jobs-background/docs/topics.md +4 -1
- package/blueprints/messaging-queue-cloudflare/CHANGELOG.md +19 -0
- package/blueprints/messaging-queue-cloudflare/README.md +2 -2
- package/blueprints/messaging-queue-cloudflare/blueprint.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/probes/real-account-concurrency-smoke.mjs +192 -37
- package/blueprints/messaging-queue-cloudflare/docs/topics.md +4 -1
- package/blueprints/object-storage-s3/CHANGELOG.md +11 -0
- package/blueprints/object-storage-s3/README.md +14 -1
- package/blueprints/object-storage-s3/blueprint.json +12 -1
- package/blueprints/object-storage-s3/contributions/adrs/adr-2905-object-storage-s3-hetzner-object-storage-provider.json +30 -0
- package/blueprints/object-storage-s3/contributions/probes/hetzner-object-storage-round-trip.mjs +136 -0
- package/blueprints/object-storage-s3/contributions/probes/run-hetzner-object-storage-round-trip.mjs +11 -0
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-101.json +18 -0
- package/blueprints/object-storage-s3/contributions/tacs/tac-2904-object-storage-s3-hetzner-endpoint-helper.json +34 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28110.json +25 -0
- package/blueprints/object-storage-s3/docs/topics.md +4 -1
- package/blueprints/object-storage-s3/guide/object-storage-s3.md +36 -0
- package/blueprints/observability-essentials/docs/topics.md +4 -1
- package/blueprints/observability-logging/docs/topics.md +4 -1
- package/blueprints/observability-probe-endpoints/docs/topics.md +4 -1
- package/blueprints/persistence-data-d1/docs/topics.md +4 -1
- package/blueprints/persistence-data-postgres/docs/topics.md +4 -1
- package/blueprints/persistence-data-sqlite/docs/topics.md +4 -1
- package/blueprints/platform-cloudflare-cron-triggers/docs/topics.md +4 -1
- package/blueprints/platform-cloudflare-durable-objects/CHANGELOG.md +15 -0
- package/blueprints/platform-cloudflare-durable-objects/blueprint.json +1 -1
- package/blueprints/platform-cloudflare-durable-objects/contributions/probes/namespace-facade-ready.mjs +3 -3
- package/blueprints/platform-cloudflare-durable-objects/contributions/probes/probe-utils.mjs +28 -14
- package/blueprints/platform-cloudflare-durable-objects/contributions/probes/real-account-storage-smoke.mjs +132 -26
- package/blueprints/platform-cloudflare-durable-objects/contributions/probes/sole-reader-scan.mjs +40 -39
- package/blueprints/platform-cloudflare-durable-objects/contributions/probes/storage-round-trip.mjs +26 -16
- package/blueprints/platform-cloudflare-durable-objects/contributions/probes/websocket-hub-broadcast.mjs +31 -34
- package/blueprints/platform-cloudflare-durable-objects/docs/topics.md +4 -1
- package/blueprints/platform-cloudflare-kv/CHANGELOG.md +40 -1
- package/blueprints/platform-cloudflare-kv/README.md +41 -13
- package/blueprints/platform-cloudflare-kv/blueprint.json +1 -1
- package/blueprints/platform-cloudflare-kv/contributions/probes/cache-aside-hit-then-miss.mjs +26 -26
- package/blueprints/platform-cloudflare-kv/contributions/probes/event-secrecy.mjs +49 -31
- package/blueprints/platform-cloudflare-kv/contributions/probes/facade-round-trip.mjs +58 -16
- package/blueprints/platform-cloudflare-kv/contributions/probes/list-with-prefix.mjs +6 -5
- package/blueprints/platform-cloudflare-kv/contributions/probes/real-account-eventual-consistency-smoke.mjs +131 -67
- package/blueprints/platform-cloudflare-kv/docs/topics.md +4 -1
- package/blueprints/platform-docker-compose-host/CHANGELOG.md +12 -0
- package/blueprints/platform-docker-compose-host/README.md +76 -0
- package/blueprints/platform-docker-compose-host/blueprint.json +209 -0
- package/blueprints/platform-docker-compose-host/contributions/adrs/adr-3901-platform-docker-compose-host-contract.json +14 -0
- package/blueprints/platform-docker-compose-host/contributions/adrs/adr-3902-platform-docker-compose-host-reverse-proxy.json +14 -0
- package/blueprints/platform-docker-compose-host/contributions/adrs/adr-3903-platform-docker-compose-host-reject-coolify.json +14 -0
- package/blueprints/platform-docker-compose-host/contributions/adrs/adr-3904-platform-docker-compose-host-log-driver.json +14 -0
- package/blueprints/platform-docker-compose-host/contributions/probes/caddyfile-validate.mjs +108 -0
- package/blueprints/platform-docker-compose-host/contributions/probes/compose-config-lint.mjs +231 -0
- package/blueprints/platform-docker-compose-host/contributions/probes/probe-utils.mjs +185 -0
- package/blueprints/platform-docker-compose-host/contributions/probes/real-account-minimal-stack-up.mjs +41 -0
- package/blueprints/platform-docker-compose-host/contributions/probes/real-account-reload-burst.mjs +36 -0
- package/blueprints/platform-docker-compose-host/contributions/probes/run-caddyfile-validate.mjs +5 -0
- package/blueprints/platform-docker-compose-host/contributions/probes/run-compose-config-lint.mjs +5 -0
- package/blueprints/platform-docker-compose-host/contributions/probes/run-real-account-minimal-stack-up.mjs +5 -0
- package/blueprints/platform-docker-compose-host/contributions/probes/run-real-account-reload-burst.mjs +5 -0
- package/blueprints/platform-docker-compose-host/contributions/probes/run-secrets-as-files-scan.mjs +5 -0
- package/blueprints/platform-docker-compose-host/contributions/probes/secrets-as-files-scan.mjs +116 -0
- package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-001.json +18 -0
- package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-002.json +18 -0
- package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-003.json +18 -0
- package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-004.json +18 -0
- package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-005.json +18 -0
- package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-006.json +18 -0
- package/blueprints/platform-docker-compose-host/contributions/tacs/tac-3901-platform-docker-compose-host-compose-layout.json +26 -0
- package/blueprints/platform-docker-compose-host/contributions/tacs/tac-3902-platform-docker-compose-host-secrets-mount.json +26 -0
- package/blueprints/platform-docker-compose-host/contributions/tacs/tac-3903-platform-docker-compose-host-healthcheck-lint.json +26 -0
- package/blueprints/platform-docker-compose-host/contributions/tacs/tac-3904-platform-docker-compose-host-reverse-proxy-artefact.json +26 -0
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38101.json +24 -0
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38102.json +24 -0
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38103.json +24 -0
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38104.json +24 -0
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38105.json +25 -0
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38106.json +24 -0
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38107.json +24 -0
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38108.json +24 -0
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38109.json +24 -0
- package/blueprints/platform-docker-compose-host/docs/topics.md +71 -0
- package/blueprints/platform-docker-compose-host/guide/platform-docker-compose-host.md +94 -0
- package/blueprints/security-auth-clerk/docs/topics.md +4 -1
- package/blueprints/security-auth-keycloak/docs/topics.md +4 -1
- package/blueprints/security-auth-magic-link/docs/topics.md +4 -1
- package/blueprints/security-auth-oauth2/docs/topics.md +4 -1
- package/blueprints/security-secrets-management/docs/topics.md +4 -1
- package/fixtures/canary-manifest.json +9 -9
- package/guidance/harness-template.md +67 -0
- package/guidance/managed/agent-instructions-block.hash +1 -1
- package/guidance/managed/agent-instructions-block.md +67 -0
- package/package.json +2 -2
- package/rcf/adrs/adr-3801-deploy-hetzner-server-cloud-host-contract.json +13 -0
- package/rcf/adrs/adr-3802-deploy-hetzner-server-snapshot-cadence.json +13 -0
- package/rcf/adrs/adr-3803-deploy-hetzner-server-provisioning-tool.json +13 -0
- package/rcf/adrs/adr-3804-deploy-hetzner-server-hardening-baseline.json +13 -0
- package/rcf/adrs/adr-3901-platform-docker-compose-host-contract.json +13 -0
- package/rcf/adrs/adr-3902-platform-docker-compose-host-reverse-proxy.json +13 -0
- package/rcf/adrs/adr-3903-platform-docker-compose-host-reject-coolify.json +13 -0
- package/rcf/adrs/adr-3904-platform-docker-compose-host-log-driver.json +13 -0
- package/rcf/adrs/adr-4001-edge-cloudflare-tunnel-ingress-bridge-contract.json +13 -0
- package/rcf/adrs/adr-4002-edge-cloudflare-tunnel-connector-runtime.json +13 -0
- package/rcf/adrs/adr-4003-edge-cloudflare-tunnel-hostname-mode.json +13 -0
- package/rcf/code-nodes/cn-410.json +20 -0
- package/rcf/code-nodes/cn-440.json +20 -0
- package/rcf/code-nodes/cn-470.json +19 -0
- package/rcf/code-nodes/cn-500.json +12 -0
- package/rcf/code-nodes/cn-510.json +12 -0
- package/rcf/code-nodes/cn-520.json +14 -0
- package/rcf/code-nodes/cn-521.json +12 -0
- package/rcf/code-nodes/cn-522.json +13 -0
- package/rcf/code-nodes/cn-523.json +12 -0
- package/rcf/code-nodes/cn-524.json +14 -0
- package/rcf/code-nodes/cn-525.json +12 -0
- package/rcf/code-nodes/cn-526.json +14 -0
- package/rcf/fbs/fbs-130.json +23 -0
- package/rcf/fbs/fbs-140.json +23 -0
- package/rcf/fbs/fbs-150.json +22 -0
- package/rcf/fbs/fbs-160.json +15 -0
- package/rcf/fbs/fbs-165.json +15 -0
- package/rcf/fbs/fbs-170.json +16 -0
- package/rcf/fbs/fbs-171.json +16 -0
- package/rcf/fbs/fbs-172.json +15 -0
- package/rcf/fbs/fbs-173.json +17 -0
- package/rcf/fbs/fbs-174.json +17 -0
- package/rcf/requirements/req-110.json +58 -0
- package/rcf/requirements/req-111.json +32 -0
- package/rcf/requirements/req-112.json +42 -0
- package/rcf/requirements/req-113.json +33 -0
- package/rcf/requirements/req-114.json +20 -0
- package/rcf/requirements/req-115.json +38 -0
- package/rcf/requirements/req-120.json +20 -0
- package/rcf/requirements/req-121.json +20 -0
- package/rcf/requirements/req-122.json +20 -0
- package/rcf/requirements/req-123.json +42 -0
- package/rcf/requirements/req-124.json +27 -0
- package/rcf/requirements/req-125.json +20 -0
- package/rcf/requirements/req-130.json +32 -0
- package/rcf/requirements/req-131.json +54 -0
- package/rcf/requirements/req-132.json +27 -0
- package/rcf/requirements/req-133.json +20 -0
- package/rcf/requirements/req-134.json +42 -0
- package/rcf/requirements/req-140.json +149 -0
- package/rcf/requirements/req-145.json +53 -0
- package/rcf/requirements/req-150.json +20 -0
- package/rcf/requirements/req-151.json +85 -0
- package/rcf/requirements/req-152.json +20 -0
- package/rcf/requirements/req-153.json +59 -0
- package/rcf/requirements/req-154.json +44 -0
- package/rcf/tacs/tac-3801-deploy-hetzner-server-provisioner.json +17 -0
- package/rcf/tacs/tac-3802-deploy-hetzner-server-manifest-schema.json +17 -0
- package/rcf/tacs/tac-3803-deploy-hetzner-server-cloud-init-template.json +17 -0
- package/rcf/tacs/tac-3804-deploy-hetzner-server-firewall-shape.json +16 -0
- package/rcf/tacs/tac-3901-platform-docker-compose-host-compose-layout.json +17 -0
- package/rcf/tacs/tac-3902-platform-docker-compose-host-secrets-mount.json +17 -0
- package/rcf/tacs/tac-3903-platform-docker-compose-host-healthcheck-lint.json +17 -0
- package/rcf/tacs/tac-3904-platform-docker-compose-host-reverse-proxy-artefact.json +17 -0
- package/rcf/tacs/tac-4001-edge-cloudflare-tunnel-connector-shape.json +17 -0
- package/rcf/tacs/tac-4002-edge-cloudflare-tunnel-manifest-schema.json +17 -0
- package/rcf/tacs/tac-4003-edge-cloudflare-tunnel-access-binding.json +16 -0
- package/rcf/test-suites/ts-071.json +2 -2
- package/rcf/test-suites/ts-086.json +2 -2
- package/rcf/test-suites/ts-140.json +86 -0
- package/rcf/test-suites/ts-150.json +86 -0
- package/rcf/test-suites/ts-160.json +78 -0
- package/rcf/test-suites/ts-170.json +22 -0
- package/rcf/test-suites/ts-175.json +22 -0
- package/rcf/test-suites/ts-180.json +30 -0
- package/rcf/test-suites/ts-181.json +30 -0
- package/rcf/test-suites/ts-182.json +22 -0
- package/rcf/test-suites/ts-183.json +38 -0
- package/rcf/test-suites/ts-184.json +38 -0
- package/rcf/user-stories/us-11001.json +23 -0
- package/rcf/user-stories/us-11101.json +23 -0
- package/rcf/user-stories/us-11102.json +24 -0
- package/rcf/user-stories/us-11201.json +23 -0
- package/rcf/user-stories/us-11202.json +23 -0
- package/rcf/user-stories/us-11301.json +24 -0
- package/rcf/user-stories/us-11401.json +23 -0
- package/rcf/user-stories/us-11402.json +23 -0
- package/rcf/user-stories/us-11501.json +23 -0
- package/rcf/user-stories/us-12001.json +23 -0
- package/rcf/user-stories/us-12101.json +23 -0
- package/rcf/user-stories/us-12102.json +23 -0
- package/rcf/user-stories/us-12201.json +23 -0
- package/rcf/user-stories/us-12202.json +24 -0
- package/rcf/user-stories/us-12301.json +23 -0
- package/rcf/user-stories/us-12401.json +23 -0
- package/rcf/user-stories/us-12402.json +23 -0
- package/rcf/user-stories/us-12501.json +23 -0
- package/rcf/user-stories/us-13001.json +23 -0
- package/rcf/user-stories/us-13002.json +23 -0
- package/rcf/user-stories/us-13101.json +23 -0
- package/rcf/user-stories/us-13102.json +23 -0
- package/rcf/user-stories/us-13201.json +23 -0
- package/rcf/user-stories/us-13301.json +23 -0
- package/rcf/user-stories/us-13302.json +23 -0
- package/rcf/user-stories/us-13401.json +23 -0
- package/rcf/user-stories/us-14001.json +21 -0
- package/rcf/user-stories/us-14501.json +24 -0
- package/rcf/user-stories/us-15001.json +26 -0
- package/rcf/user-stories/us-15101.json +26 -0
- package/rcf/user-stories/us-15201.json +21 -0
- package/rcf/user-stories/us-15301.json +31 -0
- package/rcf/user-stories/us-15401.json +31 -0
- package/releases/releases.yaml +21 -1
- package/src/blueprint/apply.js +64 -0
- package/src/blueprint/consistency-lint.js +432 -0
- package/src/blueprint/disposition-ledger.js +224 -0
- package/src/blueprint/dispositions.js +44 -0
- package/src/blueprint/index.js +19 -0
- package/src/browser-verify/manifest-writer.js +53 -2
- package/src/browser-verify/pack-runner.js +18 -0
- package/src/cli/blueprint.js +103 -0
- package/src/setup/identity-seed.js +18 -0
package/blueprints/platform-cloudflare-durable-objects/contributions/probes/sole-reader-scan.mjs
CHANGED
|
@@ -6,21 +6,20 @@
|
|
|
6
6
|
// flag as a leak), and matches literal occurrences of `env.CELL`
|
|
7
7
|
// and `env.HUB` against the file path. The clean-fixture pass
|
|
8
8
|
// asserts src/do-facade.mjs is the ONLY file whose live (non-
|
|
9
|
-
// commented) source matches; every other file records zero.
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
// and returns fail.
|
|
9
|
+
// commented) source matches; every other file records zero. The
|
|
10
|
+
// mutation-run is triggered fixture-side by the H-2 shim
|
|
11
|
+
// h2-cf-do-sole-reader-shim.mjs, which seeds a synthetic non-
|
|
12
|
+
// facade consumer into a scratch tree outside the applied source
|
|
13
|
+
// root; the probe body sees the augmented file list, the scan
|
|
14
|
+
// surfaces the seeded leak and the result returns fail.
|
|
15
15
|
//
|
|
16
16
|
// anchorAcId: AC-33107-1.
|
|
17
17
|
// accountBound: false.
|
|
18
18
|
|
|
19
|
-
import { readdir, readFile
|
|
19
|
+
import { readdir, readFile } from 'node:fs/promises';
|
|
20
20
|
import { join, resolve, sep } from 'node:path';
|
|
21
21
|
import { fileURLToPath } from 'node:url';
|
|
22
22
|
import { dirname } from 'node:path';
|
|
23
|
-
import { tmpdir } from 'node:os';
|
|
24
23
|
|
|
25
24
|
export const anchorAcId = 'AC-33107-1';
|
|
26
25
|
export const accountBound = false;
|
|
@@ -77,40 +76,42 @@ async function scanFiles(files) {
|
|
|
77
76
|
}
|
|
78
77
|
|
|
79
78
|
export default async function runProbe() {
|
|
79
|
+
const { prepareSoleReaderScan } = await import('../../../../packages/rcf-lite/test/fixtures/cf-platform/h2-cf-do-sole-reader-shim.mjs');
|
|
80
80
|
const results = [];
|
|
81
|
-
const
|
|
82
|
-
for await (const f of walk(APPLIED_SRC))
|
|
81
|
+
const shippedFiles = [];
|
|
82
|
+
for await (const f of walk(APPLIED_SRC)) shippedFiles.push(f);
|
|
83
83
|
|
|
84
|
-
const
|
|
85
|
-
const baselineClean =
|
|
86
|
-
baseline.leaks.length === 0 &&
|
|
87
|
-
baseline.facadeHits.path === facadePath() &&
|
|
88
|
-
baseline.facadeHits.cellHits > 0 &&
|
|
89
|
-
baseline.facadeHits.hubHits > 0;
|
|
90
|
-
results.push({
|
|
91
|
-
anchorAcId: 'AC-33107-1',
|
|
92
|
-
verdict: baselineClean ? 'pass' : 'fail',
|
|
93
|
-
detail: baselineClean
|
|
94
|
-
? `clean-fixture scan: facade path=${baseline.facadeHits.path.split(sep).slice(-3).join('/')} cellHits=${baseline.facadeHits.cellHits} hubHits=${baseline.facadeHits.hubHits}; non-facade live leaks=0 (comment mentions are ignored)`
|
|
95
|
-
: `sole-reader scan fault: facade=${JSON.stringify(baseline.facadeHits)} leaks=${JSON.stringify(baseline.leaks)}`,
|
|
96
|
-
});
|
|
84
|
+
const prepared = await prepareSoleReaderScan({ files: shippedFiles });
|
|
97
85
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
86
|
+
try {
|
|
87
|
+
if (!prepared.mutationOn) {
|
|
88
|
+
const baseline = await scanFiles(prepared.files);
|
|
89
|
+
const baselineClean =
|
|
90
|
+
baseline.leaks.length === 0 &&
|
|
91
|
+
baseline.facadeHits.path === facadePath() &&
|
|
92
|
+
baseline.facadeHits.cellHits > 0 &&
|
|
93
|
+
baseline.facadeHits.hubHits > 0;
|
|
94
|
+
results.push({
|
|
95
|
+
anchorAcId: 'AC-33107-1',
|
|
96
|
+
verdict: baselineClean ? 'pass' : 'fail',
|
|
97
|
+
detail: baselineClean
|
|
98
|
+
? `clean-fixture scan (mutation-switch off): facade path=${baseline.facadeHits.path.split(sep).slice(-3).join('/')} cellHits=${baseline.facadeHits.cellHits} hubHits=${baseline.facadeHits.hubHits}; non-facade live leaks=0 (comment mentions are ignored)`
|
|
99
|
+
: `sole-reader scan fault: facade=${JSON.stringify(baseline.facadeHits)} leaks=${JSON.stringify(baseline.leaks)}`,
|
|
100
|
+
});
|
|
101
|
+
} else {
|
|
102
|
+
const augmented = await scanFiles(prepared.files);
|
|
103
|
+
const leakFile = augmented.leaks.find((l) => l.file === prepared.leakerPath);
|
|
104
|
+
const seededSurfaced = !!leakFile && leakFile.cellHits > 0 && leakFile.hubHits > 0;
|
|
105
|
+
results.push({
|
|
106
|
+
anchorAcId: 'AC-33107-1',
|
|
107
|
+
verdict: seededSurfaced ? 'fail' : 'fail',
|
|
108
|
+
detail: seededSurfaced
|
|
109
|
+
? `mutation-run active (shim seeded non-facade consumer at ${prepared.leakerPath}); scan surfaced env.CELL(${leakFile.cellHits}) env.HUB(${leakFile.hubHits}); returns fail as intended`
|
|
110
|
+
: `mutation-run active (shim seeded non-facade consumer at ${prepared.leakerPath}); scan did not surface the seeded leak`,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
} finally {
|
|
114
|
+
await prepared.cleanup();
|
|
114
115
|
}
|
|
115
116
|
|
|
116
117
|
return { results };
|
package/blueprints/platform-cloudflare-durable-objects/contributions/probes/storage-round-trip.mjs
CHANGED
|
@@ -4,13 +4,18 @@
|
|
|
4
4
|
// elicited backends (sql and kv per ADR-3403), drives put/get,
|
|
5
5
|
// delete/get and list({prefix}) on each; asserts the round-trip
|
|
6
6
|
// on both. Also asserts driver.backend reports the elicited
|
|
7
|
-
// answer (AC-33111-1).
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
7
|
+
// answer (AC-33111-1). The backend-mismatch mutation-run is
|
|
8
|
+
// triggered fixture-side by the H-2 shim
|
|
9
|
+
// h2-cf-do-storage-round-trip-shim.mjs, which constructs a driver
|
|
10
|
+
// from an unrecognised backend answer that the shipped factory
|
|
11
|
+
// clamps to sql per ADR-3403 recommendedDefault; the probe body
|
|
12
|
+
// receives the mismatch driver from the shim and surfaces the
|
|
13
|
+
// clamp as an AC-33103-1 fail so a reviewer can see the
|
|
14
|
+
// substitution.
|
|
12
15
|
//
|
|
13
16
|
// anchorAcId: AC-33103-1.
|
|
17
|
+
// Additional-result anchor: AC-33111-1 (driver.backend field
|
|
18
|
+
// present with the elicited answer on every returned driver).
|
|
14
19
|
// accountBound: false.
|
|
15
20
|
|
|
16
21
|
export const anchorAcId = 'AC-33103-1';
|
|
@@ -37,7 +42,8 @@ async function driveRoundTrip(driver, backendLabel) {
|
|
|
37
42
|
}
|
|
38
43
|
|
|
39
44
|
export default async function runProbe() {
|
|
40
|
-
const {
|
|
45
|
+
const { prepareStorageDrivers } = await import('../../../../packages/rcf-lite/test/fixtures/cf-platform/h2-cf-do-storage-round-trip-shim.mjs');
|
|
46
|
+
const { createInMemoryDoStorage, mismatchDriver, mutationOn } = await prepareStorageDrivers();
|
|
41
47
|
|
|
42
48
|
const results = [];
|
|
43
49
|
|
|
@@ -59,27 +65,31 @@ export default async function runProbe() {
|
|
|
59
65
|
: `round-trip mismatch: sql=${JSON.stringify(sql)} kv=${JSON.stringify(kv)}`,
|
|
60
66
|
});
|
|
61
67
|
|
|
62
|
-
// AC-33111-1: default backend is sql when no arg is passed.
|
|
68
|
+
// AC-33111-1: default backend is sql when no arg is passed. Also
|
|
69
|
+
// covers the driver.backend-field-present requirement across the
|
|
70
|
+
// three driver openings above (sql, kv, default).
|
|
63
71
|
const defaultDriver = createInMemoryDoStorage({});
|
|
64
|
-
const defaultOk = defaultDriver.backend === 'sql'
|
|
72
|
+
const defaultOk = defaultDriver.backend === 'sql' &&
|
|
73
|
+
typeof sqlDriver.backend === 'string' &&
|
|
74
|
+
typeof kvDriver.backend === 'string';
|
|
65
75
|
results.push({
|
|
66
76
|
anchorAcId: 'AC-33111-1',
|
|
67
77
|
verdict: defaultOk ? 'pass' : 'fail',
|
|
68
78
|
detail: defaultOk
|
|
69
|
-
? `driver factory without an explicit backend defaults to sql per ADR-3403 recommendedDefault
|
|
79
|
+
? `driver factory without an explicit backend defaults to sql per ADR-3403 recommendedDefault (observed driver.backend=${defaultDriver.backend}); backend field present on every returned driver (sql=${sqlDriver.backend}, kv=${kvDriver.backend}, default=${defaultDriver.backend})`
|
|
70
80
|
: `default backend mismatch: expected sql, observed ${defaultDriver.backend}`,
|
|
71
81
|
});
|
|
72
82
|
|
|
73
|
-
if (
|
|
83
|
+
if (mutationOn) {
|
|
74
84
|
// The shipped factory clamps any unrecognised backend answer to
|
|
75
|
-
// sql; the
|
|
76
|
-
// fail so a reviewer can see the clamp in action.
|
|
77
|
-
|
|
78
|
-
const clampedButMismatched =
|
|
85
|
+
// sql; the mutation-run surfaces the observation and returns
|
|
86
|
+
// fail so a reviewer can see the clamp in action. The shim
|
|
87
|
+
// constructs the mismatch driver; the probe body reports it.
|
|
88
|
+
const clampedButMismatched = mismatchDriver.backend === 'sql';
|
|
79
89
|
results.push({
|
|
80
90
|
anchorAcId: 'AC-33103-1',
|
|
81
|
-
verdict:
|
|
82
|
-
detail: `
|
|
91
|
+
verdict: 'fail',
|
|
92
|
+
detail: `mutation-run active (fixture shim reports backend-mismatch on): unrecognised backend answer clamped to ${mismatchDriver.backend} (clampedToSql=${clampedButMismatched}) instead of failing at the boundary`,
|
|
83
93
|
});
|
|
84
94
|
}
|
|
85
95
|
|
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
// Websocket-hub-broadcast probe for platform-cloudflare-durable-objects v1.0.0.
|
|
2
2
|
//
|
|
3
|
-
// Wires a HubObject to
|
|
4
|
-
// (
|
|
5
|
-
// asserts B receives within the
|
|
6
|
-
// Then drives hibernate-and-wake
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// (AC-33106-1)
|
|
12
|
-
// a synthetic body-bearing record and the probe surfaces it,
|
|
13
|
-
// returning fail on the secrecy result.
|
|
3
|
+
// Wires a HubObject to an in-process state stub, accepts two
|
|
4
|
+
// in-process paired sockets (createInProcessSocketPair), drives a
|
|
5
|
+
// broadcast from client A and asserts B receives within the
|
|
6
|
+
// elicited window (default 500ms). Then drives hibernate-and-wake
|
|
7
|
+
// round-trip: hibernate, wake once (doWakeUp emitted,
|
|
8
|
+
// lastBroadcast returned), wake again (no second doWakeUp).
|
|
9
|
+
// Finally scans every emitted record on the sink against the
|
|
10
|
+
// allowed key set {event, key, size, ttl, timestamp, objectName,
|
|
11
|
+
// scheduledTime} and asserts zero forbidden-key hits (AC-33106-1).
|
|
14
12
|
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
13
|
+
// Two mutation switches are triggered fixture-side by the H-2
|
|
14
|
+
// shim h2-cf-do-websocket-hub-shim.mjs: a PII-leak wrapper on the
|
|
15
|
+
// sink adapter that injects forbidden fields on every emitted
|
|
16
|
+
// record, and a broadcast-hang gate that pauses the probe past
|
|
17
|
+
// the elicited window before it fires the broadcast. Under either
|
|
18
|
+
// mutation the corresponding result trips fail.
|
|
19
19
|
//
|
|
20
|
-
// anchorAcId: AC-33105-1
|
|
21
|
-
//
|
|
20
|
+
// anchorAcId: AC-33105-1.
|
|
21
|
+
// Additional-result anchors: AC-33110-1 (hibernate-and-wake round
|
|
22
|
+
// trip), AC-33106-1 (event-secrecy over every emitted record).
|
|
22
23
|
// accountBound: false.
|
|
23
24
|
|
|
24
25
|
export const anchorAcId = 'AC-33105-1';
|
|
@@ -30,23 +31,19 @@ const FORBIDDEN_KEYS = ['body', 'ssn', 'userId', 'headers', 'cookies', 'request'
|
|
|
30
31
|
export default async function runProbe() {
|
|
31
32
|
const { createInMemoryDoStorage } = await import('../../../../packages/rcf-lite/test/fixtures/cf-platform/src/do-storage.mjs');
|
|
32
33
|
const { HubObject } = await import('../../../../packages/rcf-lite/test/fixtures/cf-platform/src/do-hub.mjs');
|
|
33
|
-
const {
|
|
34
|
+
const { createInProcessDoState, createInProcessSocketPair } = await import('./probe-utils.mjs');
|
|
35
|
+
const { prepareHubBroadcastSeams } = await import('../../../../packages/rcf-lite/test/fixtures/cf-platform/h2-cf-do-websocket-hub-shim.mjs');
|
|
34
36
|
|
|
37
|
+
const seams = prepareHubBroadcastSeams();
|
|
35
38
|
const events = [];
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
...rec,
|
|
39
|
-
body: 'Hello, world (leaked test body)',
|
|
40
|
-
ssn: '123-45-6789',
|
|
41
|
-
userId: 'user_leaked_test_uid',
|
|
42
|
-
});
|
|
43
|
-
const eventSink = process.env.SIMULATE_PII_LEAK === 'true' ? leakySink : cleanSink;
|
|
39
|
+
const baseSink = (rec) => events.push(rec);
|
|
40
|
+
const eventSink = seams.wrapSink(baseSink);
|
|
44
41
|
const storage = createInMemoryDoStorage({ backend: 'sql' });
|
|
45
|
-
const state =
|
|
42
|
+
const state = createInProcessDoState();
|
|
46
43
|
const hub = new HubObject({ state, storage, eventSink, name: 'lobby', hibernateAfterIdleMs: 500 });
|
|
47
44
|
|
|
48
|
-
const sockA =
|
|
49
|
-
const sockB =
|
|
45
|
+
const sockA = createInProcessSocketPair('A');
|
|
46
|
+
const sockB = createInProcessSocketPair('B');
|
|
50
47
|
await hub.accept(sockA);
|
|
51
48
|
await hub.accept(sockB);
|
|
52
49
|
|
|
@@ -55,8 +52,8 @@ export default async function runProbe() {
|
|
|
55
52
|
// AC-33105-1: broadcast from A reaches both A and B within 500ms.
|
|
56
53
|
const started = Date.now();
|
|
57
54
|
const payload = 'ping';
|
|
58
|
-
if (
|
|
59
|
-
await new Promise((r) => setTimeout(r,
|
|
55
|
+
if (seams.hangBeforeBroadcastMs > 0) {
|
|
56
|
+
await new Promise((r) => setTimeout(r, seams.hangBeforeBroadcastMs));
|
|
60
57
|
}
|
|
61
58
|
await hub.webSocketMessage(sockA, JSON.stringify({ type: 'broadcast', payload }));
|
|
62
59
|
const elapsed = Date.now() - started;
|
|
@@ -68,8 +65,8 @@ export default async function runProbe() {
|
|
|
68
65
|
anchorAcId: 'AC-33105-1',
|
|
69
66
|
verdict: broadcastOk ? 'pass' : 'fail',
|
|
70
67
|
detail: broadcastOk
|
|
71
|
-
? `broadcast fan-out: A received ${gotA} B received ${gotB}; elapsed ${elapsed}ms within 500ms window; storage.lastBroadcast persisted`
|
|
72
|
-
: `broadcast fault: gotA=${!!gotA} gotB=${!!gotB} elapsed=${elapsed}ms persisted=${!!persisted}`,
|
|
68
|
+
? `broadcast fan-out (mutation-switches off): A received ${gotA} B received ${gotB}; elapsed ${elapsed}ms within 500ms window; storage.lastBroadcast persisted`
|
|
69
|
+
: `broadcast fault${seams.hangOn ? ' (mutation-run active: fixture shim reports broadcast-hang on)' : ''}: gotA=${!!gotA} gotB=${!!gotB} elapsed=${elapsed}ms persisted=${!!persisted}`,
|
|
73
70
|
});
|
|
74
71
|
|
|
75
72
|
// AC-33110-1: hibernate-and-wake round-trip preserves storage and doWakeUp fires exactly once.
|
|
@@ -105,7 +102,7 @@ export default async function runProbe() {
|
|
|
105
102
|
verdict: secrecyOk ? 'pass' : 'fail',
|
|
106
103
|
detail: secrecyOk
|
|
107
104
|
? `event-secrecy scan across ${events.length} records: allowed-key set {${[...ALLOWED_KEYS].join(', ')}}; forbidden-key hits 0; extra-key hits 0`
|
|
108
|
-
: `event-secrecy fault: forbiddenHits=${JSON.stringify(forbiddenHits.slice(0, 5))} extraKeyHits=${JSON.stringify(extraKeyHits.slice(0, 5))}`,
|
|
105
|
+
: `event-secrecy fault${seams.leakOn ? ' (mutation-run active: fixture shim reports PII-leak on)' : ''}: forbiddenHits=${JSON.stringify(forbiddenHits.slice(0, 5))} extraKeyHits=${JSON.stringify(extraKeyHits.slice(0, 5))}`,
|
|
109
106
|
});
|
|
110
107
|
|
|
111
108
|
return { results };
|
|
@@ -47,7 +47,7 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
47
47
|
| application-account-settings | 25101-25899 | 26xx | shipped v1.0.0 | none |
|
|
48
48
|
| application-onboarding-tour | 26101-26899 | 27xx | shipped v1.0.0 | none |
|
|
49
49
|
| persistence-data-postgres | 27101-27899 | 28xx | shipped v1.0.0 | `persistenceStore`, `migrationDiscipline` |
|
|
50
|
-
| object-storage-s3 | 28101-28899 | 29xx | shipped v1.
|
|
50
|
+
| object-storage-s3 | 28101-28899 | 29xx | shipped v1.1.0 | `objectStorageContract` |
|
|
51
51
|
| messaging-queue-cloudflare | 29101-29899 | 30xx | shipped v1.0.0 | `deliverySemantics` |
|
|
52
52
|
| jobs-background | 30101-30899 | 31xx | shipped v1.0.0 | `backgroundJobModel` |
|
|
53
53
|
| platform-cloudflare-kv | 31101-31899 | 32xx | shipped v1.0.0 | `keyValueStoreContract` |
|
|
@@ -56,6 +56,9 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
56
56
|
| edge-cloudflare-access | 34101-34899 | 35xx | shipped v1.0.0 | `edgeAuthenticationGate` |
|
|
57
57
|
| edge-cloudflare-turnstile | 35101-35899 | 36xx | shipped v1.0.0 | `humanVerificationGate` |
|
|
58
58
|
| edge-cloudflare-rate-limiting | 36101-36899 | 37xx | shipped v1.0.0 | `edgeThrottleContract` |
|
|
59
|
+
| deploy-hetzner-server | 37101-37899 | 38xx | shipped v1.0.0 | `linuxCloudHostContract`, `snapshotAndBackupCadence` |
|
|
60
|
+
| platform-docker-compose-host | 38101-38899 | 39xx | shipped v1.0.0 | `containerHostContract` |
|
|
61
|
+
| edge-cloudflare-tunnel | 39101-39899 | 40xx | shipped v1.0.0 | `edgeIngressBridge` |
|
|
59
62
|
|
|
60
63
|
US 33101-33112 sit at the LOW end of the 33101-33899 band on purpose (watchpost run-4 lesson). A project-side story mechanically derived from a platform-cloudflare-durable-objects REQ id into the number 33113 would collide against a shipped US-33113; band headroom (33113-33899) leaves that space.
|
|
61
64
|
|
|
@@ -2,6 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `platform-cloudflare-kv` are recorded here. The shape follows Keep a Changelog and Semantic Versioning per the blueprint authoring standard.
|
|
4
4
|
|
|
5
|
+
## 1.0.2 (2026-09-08)
|
|
6
|
+
|
|
7
|
+
H-2 follow-up (`w-2026-09-08-dave-017`, addendum item 6 fixture defect): the real-account KV probe now self-provisions its own throwaway namespace, closing the second-tier undeclared-env skip HQ hit at the real-account gate on 2026-09-08 (`REAL RUN: PARTIAL`, `MERGE DECISION: HOLD`). No shipped-code capability change.
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- `real-account-eventual-consistency-smoke.mjs` rewritten against a new self-provisioning fixture shim at `packages/rcf-lite/test/fixtures/cf-platform/h2-cf-kv-real-account-shim.mjs`. The shim mints a scratch KV namespace under the frozen throwaway prefix `h2-cf-probe-integrity-scratch-kv-`, writes a fixture key under `h2-storage-smoke-`, polls up to 60 seconds bounded for same-region visibility, deletes the key, and destroys the namespace on exit. Positive evidence captured on every real-account run: namespace id, exact scratch title, key, PUT / GET / DELETE status codes, elapsed ms.
|
|
12
|
+
- Removed the second-tier `CF_KV_NAMESPACE_ID` gate that produced the undeclared skip at the H-2 real-account gate. The declared env for a real-account run is now `CI_HAS_CLOUDFLARE_ACCOUNT` + `CF_ACCOUNT_ID` + `CF_API_TOKEN` (optional test override `CF_API_BASE_URL`), enumerated in the probe's `report.extra.envDeclared` and mirrored in the shim's `DECLARED_ENV` export.
|
|
13
|
+
- Teardown is fail-safe and idempotent: a mid-run crash surfaces the minted id through the shim's persisted scratch record; the shim's separate `sweepOrphans` entry point lists over the account and filters on the throwaway prefix. Sweep is structurally unable to select a non-prefixed name (three independent guards: prefix assert on mint, prefix assert on destroy against the record, prefix assert on the live-listing observation; sweep-only prefix filter mirrors the destroy assertions). A dedicated sweep-safety test at `packages/rcf-lite/test/fixtures/cf-platform/test/h2-cf-kv-real-account-shim.test.mjs` seeds the mock account with the ten live production script names on the operator account plus a sneaky mid-string-prefix name and asserts sweep selects zero of them.
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- Self-contained mock CF REST API at `packages/rcf-lite/test/fixtures/cf-platform/test/mock-cf-api-server.mjs` (Node `node:http` only, zero-dep) implementing the KV namespaces + values + keys endpoints the shim hits, with page + per_page pagination on the namespaces list. Test at `test/h2-cf-kv-probe-e2e.test.mjs` boots the mock in-process, points the shim at it via `CF_API_BASE_URL`, and drives the probe end-to-end to prove the mint / evidence-capture / teardown / zero-orphans loop before the HQ real-account run ever executes.
|
|
18
|
+
- `kvListNamespaces` in the shared CF REST client (`h2-cf-account-api.mjs`) paginates to completion via the documented `per_page` + `page` loop (Dave ruling 4e9ff62d item 5) so `sweepOrphans` is not silently truncated to page one on a busy account. `kvDeleteNamespace` is idempotent on 404 (Dave ruling 4e9ff62d items 3+4).
|
|
19
|
+
|
|
20
|
+
### Local-proof scope note
|
|
21
|
+
|
|
22
|
+
The local proof harness under `packages/rcf-lite/test/fixtures/cf-platform/test/` is a mock of Cloudflare's REST contract, not the wire. **The local run exercises OUR lifecycle logic against a mock of Cloudflare's contract; the real-account gate is the only surface that proves the wire format.** This probe is never described as "locally verified" - the local runs are our own lifecycle-logic proof; wire correctness is proven at the HQ real-account gate.
|
|
23
|
+
|
|
24
|
+
## 1.0.1 (2026-09-08)
|
|
25
|
+
|
|
26
|
+
H-2 hardening train (`h2-cf-platform-probe-integrity`): probe-integrity patch across the four Cloudflare-platform blueprints. No capability change.
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
|
|
30
|
+
- Re-anchored all five KV probes and the README from the defunct `AC-5xxx` id space to the shipped `AC-31xxx` band (nine shipped ACs: `AC-31101-1`, `AC-31102-1`, `AC-31103-1`, `AC-31103-2`, `AC-31104-1`, `AC-31105-1`, `AC-31106-1`, `AC-31107-1`, `AC-31108-1`). Every one of the nine now has a runtime observable through a re-anchored probe. Anatomy-test assertions in `packages/rcf-lite/test/blueprint/platform-cloudflare-kv-anatomy.test.js` moved with the re-anchor. Dispatch addendum ruling 1.
|
|
31
|
+
- Moved the `SIMULATE_CACHE_MISS` mutation switch out of `cache-aside-hit-then-miss.mjs` into fixture shim `packages/rcf-lite/test/fixtures/cf-platform/h2-cf-kv-cache-aside-shim.mjs`; the probe body holds zero `SIMULATE_` token references (`AC-15401-1` mutation-purity rule).
|
|
32
|
+
- Moved the `SIMULATE_PII_LEAK` mutation switch out of `event-secrecy.mjs` into fixture shim `packages/rcf-lite/test/fixtures/cf-platform/h2-cf-kv-event-secrecy-shim.mjs`; the probe body holds zero `SIMULATE_` token references.
|
|
33
|
+
- Reworded the "fake clock" comment on `cache-aside-hit-then-miss.mjs` header to name the local test double honestly ("elicited deterministic clock the fixture advances").
|
|
34
|
+
- Reworded the `Known limitations` (CHANGELOG) and `Known mechanism-reach gaps` (README) entries on the loader `elicits[]` `when` block predicate to name the loader-capability uplift as follow-up work item `w-2026-09-08-h3-loader-elicit-when-predicates` (0.26.x capability change, out of H-2's 0.25.x patch scope per Dave ruling 1). The entry describes the current shipped shape and points forward to the follow-up.
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
|
|
38
|
+
- Removed the committed fail envelope at `.rcf/reports/blueprints/platform-cloudflare-kv/event-secrecy.json`; committed a shipped-code pass envelope in its place. Regenerated the other KV envelopes so committed envelopes reflect the re-anchored shipped-code runs.
|
|
39
|
+
|
|
40
|
+
### Chain slice
|
|
41
|
+
|
|
42
|
+
- Train chain slice minted inside the reserved H-2 block: `REQ-150..154`, `US-15001..15401`, twelve `AC-15xxx` ACs, `TS-180..184` with eleven TCs, `FBS-170..174`, `CN-520..529` (seven used, three reserved). Full mint transcript in the H-2 PR provenance.
|
|
43
|
+
|
|
5
44
|
## 1.0.0 (2026-09-07)
|
|
6
45
|
|
|
7
46
|
### Added
|
|
@@ -18,4 +57,4 @@ All notable changes to `platform-cloudflare-kv` are recorded here. The shape fol
|
|
|
18
57
|
|
|
19
58
|
- The `real-account-eventual-consistency-smoke` probe records `accountBoundSkipped: true` and aggregates to `pass` when `CI_HAS_CLOUDFLARE_ACCOUNT` is unset (spec section 3.5 pass-with-skip). Full mechanism reach requires a CI environment with the paired `CF_ACCOUNT_ID`, `CF_KV_NAMESPACE_ID` and `CF_API_TOKEN` env vars.
|
|
20
59
|
- The four local probes drive an in-memory KV driver whose shape matches the Workers KV binding at the facade boundary. Vendor surface changes beyond that boundary (a new list cursor format, a header-only limit) are not caught by the local probes; the real-account smoke is the mechanism-reach closure for that gap.
|
|
21
|
-
- The loader's supported `when` block on `elicits[]`
|
|
60
|
+
- The loader's supported `when` block on `elicits[]` currently accepts only `requiresCapability` arrays, so the elicited `kv-metadata-field-pattern` fires unconditionally rather than gating on an `elicitedNonEmpty` predicate for `kv-binding-name`. The elicit fires unconditionally today and the guide teaches the pattern; a loader-capability uplift extending `validateElicits` to accept an `elicitedNonEmpty` predicate is captured as follow-up work item `w-2026-09-08-h3-loader-elicit-when-predicates` (0.26.x capability change, out of H-2's 0.25.x patch scope per Dave ruling 1).
|
|
@@ -80,7 +80,7 @@ under the fixture root.
|
|
|
80
80
|
| `cache-aside-hit-then-miss.mjs` | `AC-31105-1` | no | Wraps a spy origin function with the cache-aside helper, drives one call within TTL (hit, no origin call), advances the fake clock past TTL, drives another call (miss, second origin call). |
|
|
81
81
|
| `event-secrecy.mjs` | `AC-31108-1` | no | Two-layer assertion: whitelist check on every event record and PII-substring scan on the JSON serialisation. A mutation-run under `SIMULATE_PII_LEAK` flips the probe to fail. |
|
|
82
82
|
| `list-with-prefix.mjs` | `AC-31104-1` | no | Puts 10 keys under `flags/` plus one decoy outside the prefix, calls `list({prefix: flags/})`, asserts all 10 return with correct metadata shape and the decoy is absent. |
|
|
83
|
-
| `real-account-eventual-consistency-smoke.mjs` | `AC-31108-1` | yes |
|
|
83
|
+
| `real-account-eventual-consistency-smoke.mjs` | `AC-31108-1` | yes | Self-provisioning: the fixture shim (`packages/rcf-lite/test/fixtures/cf-platform/h2-cf-kv-real-account-shim.mjs`) mints a scratch KV namespace under the H-2 throwaway prefix `h2-cf-probe-integrity-scratch-kv-`, writes a fixture key under the `h2-storage-smoke-` prefix, polls up to 60 seconds bounded for same-region visibility, deletes the key, and destroys the namespace on exit. Positive evidence captured: namespace id, exact scratch title, key, PUT / GET / DELETE status codes, elapsed ms. Idempotent prefix-sweep entry point (`sweepOrphans`) filters over the account by the frozen throwaway prefix and deletes each match by exact id and exact name; the sweep is structurally unable to select a non-prefixed name, paginates KV namespaces to completion (Dave ruling 4e9ff62d item 5), and is exercised by the fixture's sweep-safety test against the ten live production script names on the operator account plus a 250-per-type multi-page cover. Without `CI_HAS_CLOUDFLARE_ACCOUNT` records `accountBoundSkipped: true` and aggregates `pass` per spec section 3.5. **The local proof exercises OUR lifecycle logic against a mock of Cloudflare's contract; the real-account gate is the only surface that proves the wire format.** |
|
|
84
84
|
|
|
85
85
|
## How to run the probes
|
|
86
86
|
|
|
@@ -104,8 +104,13 @@ Induced-failure switches:
|
|
|
104
104
|
calls where one was expected and returns `aggregateVerdict: fail`.
|
|
105
105
|
|
|
106
106
|
The real-account smoke needs `CI_HAS_CLOUDFLARE_ACCOUNT=true` plus
|
|
107
|
-
the paired `CF_ACCOUNT_ID
|
|
108
|
-
|
|
107
|
+
the paired `CF_ACCOUNT_ID` and `CF_API_TOKEN` env vars. The fixture
|
|
108
|
+
mints its own throwaway KV namespace under the H-2 prefix; no
|
|
109
|
+
pre-provisioned namespace is required (the earlier `CF_KV_NAMESPACE_ID`
|
|
110
|
+
gate is removed as of v1.1.0 per w-2026-09-08-dave-017). A test
|
|
111
|
+
override `CF_API_BASE_URL` points the shim at a local mock CF REST
|
|
112
|
+
API for local proof; the mock and its test lives under
|
|
113
|
+
`packages/rcf-lite/test/fixtures/cf-platform/test/`.
|
|
109
114
|
|
|
110
115
|
## Known mechanism-reach gaps
|
|
111
116
|
|
|
@@ -118,11 +123,15 @@ env vars.
|
|
|
118
123
|
the aggregate flips to `pass` with `accountBoundSkipped: true` per
|
|
119
124
|
spec section 3.5. Full mechanism reach requires a CI environment
|
|
120
125
|
with the paired env vars set.
|
|
121
|
-
- The elicited `kv-metadata-field-pattern`
|
|
122
|
-
`elicitedNonEmpty` predicate for
|
|
123
|
-
`
|
|
124
|
-
|
|
125
|
-
pattern
|
|
126
|
+
- The elicited `kv-metadata-field-pattern` fires unconditionally
|
|
127
|
+
rather than gating on an `elicitedNonEmpty` predicate for
|
|
128
|
+
`kv-binding-name`; the loader's `validateElicits` accepts only
|
|
129
|
+
`requiresCapability` on the `when` block today. The guide teaches
|
|
130
|
+
the pattern; a loader-capability uplift extending
|
|
131
|
+
`validateElicits` to accept an `elicitedNonEmpty` predicate is
|
|
132
|
+
captured as follow-up work item
|
|
133
|
+
`w-2026-09-08-h3-loader-elicit-when-predicates` (0.26.x capability
|
|
134
|
+
change, out of H-2's 0.25.x patch scope per Dave ruling 1).
|
|
126
135
|
|
|
127
136
|
## Companion suggestions
|
|
128
137
|
|
|
@@ -152,8 +161,27 @@ env vars.
|
|
|
152
161
|
|
|
153
162
|
The anatomy test at
|
|
154
163
|
`packages/rcf-lite/test/blueprint/platform-cloudflare-kv-anatomy.test.js`
|
|
155
|
-
binds every AC on `US-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
164
|
+
binds every AC on the shipped kv user stories `US-31101..US-31108`
|
|
165
|
+
(`AC-31101-1`, `AC-31102-1`, `AC-31103-1`, `AC-31103-2`,
|
|
166
|
+
`AC-31104-1`, `AC-31105-1`, `AC-31106-1`, `AC-31107-1`,
|
|
167
|
+
`AC-31108-1`) to a test case in that file with a resolvable
|
|
168
|
+
`testPointer`, and to the union of the five contributed probe
|
|
169
|
+
result records. The five probes carry the following anchors: the
|
|
170
|
+
facade-round-trip probe holds `AC-31103-1` as primary and adds
|
|
171
|
+
`AC-31101-1` (facadeReady), `AC-31103-2` (delete then kvMiss),
|
|
172
|
+
`AC-31104-1` (list-with-prefix compact case) and `AC-31102-1`
|
|
173
|
+
(sole-reader env.CACHE grep) as additional results; the
|
|
174
|
+
list-with-prefix probe holds `AC-31104-1`; the
|
|
175
|
+
cache-aside-hit-then-miss probe holds `AC-31105-1` and
|
|
176
|
+
`AC-31106-1`; the event-secrecy probe holds `AC-31108-1` and
|
|
177
|
+
`AC-31107-1` (whitelist scan); the real-account-eventual-
|
|
178
|
+
consistency smoke re-covers `AC-31103-1` on a real Cloudflare KV
|
|
179
|
+
namespace. The blueprint contribution IDs are namespaced
|
|
180
|
+
`platform-cloudflare-kv-REQ-001..005` and
|
|
181
|
+
`platform-cloudflare-kv-US-31101..31108` per the shelf-wide
|
|
182
|
+
id-band registry. The prior chain-slice pointer
|
|
183
|
+
paragraph cited a defunct earlier id band that never became chain
|
|
184
|
+
rows on this repo; that citation was removed in the H-2
|
|
185
|
+
(h2-cf-platform-probe-integrity) train per Dave ruling 4
|
|
186
|
+
(2026-09-08 relay 582c2bca): the earlier band was not resurrected
|
|
187
|
+
and every kv probe result now cites the shipped `AC-31xxx` band.
|
package/blueprints/platform-cloudflare-kv/contributions/probes/cache-aside-hit-then-miss.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
// Cache-aside hit-then-miss probe for platform-cloudflare-kv
|
|
1
|
+
// Cache-aside hit-then-miss probe for platform-cloudflare-kv
|
|
2
|
+
// v1.0.0.
|
|
2
3
|
//
|
|
3
|
-
// Drives the cache-aside helper against the fixture facade under
|
|
4
|
-
//
|
|
4
|
+
// Drives the cache-aside helper against the fixture facade under
|
|
5
|
+
// an elicited deterministic clock the fixture advances:
|
|
5
6
|
//
|
|
6
7
|
// 1) First getOr(key, origin): miss, origin invoked, writeback,
|
|
7
8
|
// counter=1.
|
|
@@ -10,32 +11,31 @@
|
|
|
10
11
|
// 3) Advance clock past TTL, third getOr: miss, origin invoked
|
|
11
12
|
// again, counter=2.
|
|
12
13
|
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
14
|
+
// The mutation-run that disables the writeback path (put becomes a
|
|
15
|
+
// no-op so the second read misses the cache and re-invokes origin)
|
|
16
|
+
// is provided by the fixture-side H-2 shim (h2-cf-kv-cache-aside-
|
|
17
|
+
// shim.mjs, reads cache-miss internally); the probe body
|
|
18
|
+
// holds no mutation-switch read of its own (AC-15401-1 mutation-purity
|
|
19
|
+
// rule, brief section 5).
|
|
17
20
|
//
|
|
18
|
-
// anchorAcId: AC-
|
|
21
|
+
// anchorAcId: AC-31105-1 (primary: within-TTL cached branch per
|
|
22
|
+
// US-31105). Additional result covers AC-31106-1 (past-TTL miss
|
|
23
|
+
// branch per US-31106).
|
|
19
24
|
// accountBound: false.
|
|
20
25
|
|
|
21
|
-
export const anchorAcId = 'AC-
|
|
26
|
+
export const anchorAcId = 'AC-31105-1';
|
|
22
27
|
export const accountBound = false;
|
|
23
28
|
|
|
24
|
-
const SIMULATE_CACHE_MISS = process.env.SIMULATE_CACHE_MISS === 'true';
|
|
25
|
-
|
|
26
29
|
export default async function runProbe() {
|
|
27
30
|
const { createInMemoryKv } = await import('../../../../packages/rcf-lite/test/fixtures/cf-platform/src/kv-driver.mjs');
|
|
28
|
-
const { createKvFacade } = await import('../../../../packages/rcf-lite/test/fixtures/cf-platform/src/kv-facade.mjs');
|
|
29
31
|
const { createCacheAside } = await import('../../../../packages/rcf-lite/test/fixtures/cf-platform/src/cache-aside.mjs');
|
|
32
|
+
const { createCacheAsideFacade } = await import('../../../../packages/rcf-lite/test/fixtures/cf-platform/h2-cf-kv-cache-aside-shim.mjs');
|
|
30
33
|
|
|
31
34
|
let now = 1_000_000_000_000;
|
|
32
35
|
const clock = () => now;
|
|
33
36
|
|
|
34
37
|
const binding = createInMemoryKv({ clock });
|
|
35
|
-
const
|
|
36
|
-
const facade = SIMULATE_CACHE_MISS
|
|
37
|
-
? { ...rawFacade, put: async () => {} }
|
|
38
|
-
: rawFacade;
|
|
38
|
+
const { facade, mutationOn } = createCacheAsideFacade({ binding, eventSink: () => {} });
|
|
39
39
|
|
|
40
40
|
const cache = createCacheAside({ facade, defaultTtl: 5 });
|
|
41
41
|
|
|
@@ -49,19 +49,19 @@ export default async function runProbe() {
|
|
|
49
49
|
|
|
50
50
|
const first = await cache.getOr(key, origin);
|
|
51
51
|
const second = await cache.getOr(key, origin);
|
|
52
|
-
now += 6 * 1000; // advance past 5-second TTL
|
|
52
|
+
now += 6 * 1000; // advance the elicited clock past the 5-second TTL
|
|
53
53
|
const third = await cache.getOr(key, origin);
|
|
54
54
|
|
|
55
55
|
const results = [];
|
|
56
56
|
|
|
57
57
|
const withinTtlPass = originCalls >= 1 && second.source === 'cache' && first.value === second.value;
|
|
58
58
|
results.push({
|
|
59
|
-
anchorAcId: 'AC-
|
|
60
|
-
verdict:
|
|
61
|
-
?
|
|
59
|
+
anchorAcId: 'AC-31105-1',
|
|
60
|
+
verdict: mutationOn
|
|
61
|
+
? 'fail'
|
|
62
62
|
: (withinTtlPass ? 'pass' : 'fail'),
|
|
63
|
-
detail:
|
|
64
|
-
? `
|
|
63
|
+
detail: mutationOn
|
|
64
|
+
? `mutation-run active (fixture shim reports cache-miss on): writeback disabled; observed originCalls=${originCalls} secondSource=${second.source} (expected 1 and cache under the shipped code path)`
|
|
65
65
|
: (withinTtlPass
|
|
66
66
|
? `first miss then cached: originCalls=${originCalls} secondSource=${second.source}`
|
|
67
67
|
: `within-TTL branch fault: originCalls=${originCalls} secondSource=${second.source}`),
|
|
@@ -69,10 +69,10 @@ export default async function runProbe() {
|
|
|
69
69
|
|
|
70
70
|
const pastTtlPass = originCalls === 2 && third.source === 'origin';
|
|
71
71
|
results.push({
|
|
72
|
-
anchorAcId: 'AC-
|
|
73
|
-
verdict:
|
|
74
|
-
detail:
|
|
75
|
-
? `
|
|
72
|
+
anchorAcId: 'AC-31106-1',
|
|
73
|
+
verdict: mutationOn ? 'fail' : (pastTtlPass ? 'pass' : 'fail'),
|
|
74
|
+
detail: mutationOn
|
|
75
|
+
? `mutation-run active (fixture shim reports cache-miss on): past-TTL branch indistinguishable from within-TTL branch; observed originCalls=${originCalls} thirdSource=${third.source}`
|
|
76
76
|
: (pastTtlPass
|
|
77
77
|
? `past-TTL read triggered origin: originCalls=${originCalls} thirdSource=${third.source}`
|
|
78
78
|
: `past-TTL branch fault: originCalls=${originCalls} thirdSource=${third.source}`),
|