From 2789efcefa52be16ed526fa5d8d06a4b007a2730 Mon Sep 17 00:00:00 2001 From: Sam Gbafa Date: Sat, 17 Oct 2026 05:41:08 +0000 Subject: [PATCH] ops(TC-1164): make billing the quota authority for Sam's spaces --- docs/releasing.md | 39 ++++++++++++++++++------------ ops/quota-overrides.json | 8 +++--- scripts/ci/reconcile-quota.py | 4 +-- scripts/ci/test-quota-authority.py | 28 ++++++++++++++++++++- 4 files changed, 56 insertions(+), 23 deletions(-) diff --git a/docs/releasing.md b/docs/releasing.md index f033fee6..e4e45720 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -152,22 +152,29 @@ not N0-specific or permission to silently reuse old values. Missing authorization or missing/unknown authority fails before any compose, CVM or whitelist mutation. -`authority=node-override` currently applies the reviewed limits after the -last restart and required health. Both exact spaces must exist once with -positive usage in authenticated `/admin/usage`. Before ANY PUT, both billing -storage-comp reads must prove no active comp: 404 logs only -`billing storage-comp unavailable`; valid `active:false` also permits the -legacy restore. Active comp fails `authority mismatch: flip to billing`. -Auth/5xx/transport/malformed responses fail closed, never count as absence. -Each PUT requires GET readback of both override and effective values. - -The later reviewed authority flip to `billing` is separate from this PR and -follows TC-1162 migration. Billing mode never PUTs/DELETEs a node override: -active absolute per-space `storage_limit_bytes` must cover each reviewed -floor, and node GET must show `override_bytes=null`. A non-null override -fails `stale legacy override`. A cold node cache is not a failure: billing -is authoritative and the node fetches on the next write (≤60 s TTL). -Do not compare incremental account `comp_bytes` with absolute space limits. +`authority=billing` is current (TC-1162/TC-1164): billing is the quota +authority for both of Sam's spaces, and the reviewed limits are floors, +applications `5368709120` and secrets `1073741824` (internal D1 +`quota_overrides`). Billing mode is read-only after the last restart and +required health: both exact spaces must exist once with positive usage in +authenticated `/admin/usage`; it never PUTs/DELETEs a node override. Each +active absolute per-space `storage_limit_bytes` must cover its floor, and +node GET must show `override_bytes=null`. Missing, inactive or insufficient +comps fail `billing authority does not cover both reviewed quota floors`; a +non-null override fails `stale legacy override`. A cold node cache is not a +failure: billing is authoritative and the node fetches on the next write +(≤60 s TTL). Do not compare incremental account `comp_bytes` with absolute +space limits. + +Ordering rule: the flip to `billing` is merged only after both spaces are +billing comps with their node overrides cleared, and before any further +`deploy_phala` dispatch. Reverting to `authority=node-override` requires a +reviewed PR. In that legacy mode, before ANY PUT both billing storage-comp +reads must prove no active comp (404 logs only `billing storage-comp +unavailable`; valid `active:false` also permits the restore); an active comp +fails `authority mismatch: flip to billing`. Each PUT requires GET readback +of both override and effective values. In both modes, auth/5xx/transport/ +malformed responses fail closed and never count as absence. No raw response, identity list, credential or error body is logged. Any attempted restart without verified reconciliation is fatal **OVERRIDES UNVERIFIED**, requiring authorized operator/TC-1161 fallback. diff --git a/ops/quota-overrides.json b/ops/quota-overrides.json index b5899847..ec0fcde8 100644 --- a/ops/quota-overrides.json +++ b/ops/quota-overrides.json @@ -1,13 +1,13 @@ { - "authority": "node-override", + "authority": "billing", "overrides": { "tinycloud:pkh:eip155:1:0xd559CCd9EB87c530A9a349262669386dE93cf412:applications": { "limit_bytes": 5368709120, - "_comment": "Confirmed by Amos's read-only TC-1161 D1 quota_overrides and quota_override_audit extract, 2026-10-16: applied 2026-10-16T17:37:16Z, last_node_status 200. Sam authorizes these values; every deployment requires fresh authorize_quota_values opt-in. Flip authority to billing only through a separate reviewed PR after TC-1162 migration. Prove both exact spaces and positive usage, and reject active billing comp before any legacy node PUT." + "_comment": "Billing-mode FLOOR, verified read-only after each authorized deploy: billing /api/admin/storage-comp storage_limit_bytes must be >= this floor and node override_bytes must be null. Value from internal D1 quota_overrides (applications 5368709120), migrated to a billing comp via /storage (TC-1162/TC-1164). Merge only after that migration is verified." }, "tinycloud:pkh:eip155:1:0xd559CCd9EB87c530A9a349262669386dE93cf412:secrets": { - "limit_bytes": 268721121, - "_comment": "Space ID verified read-only by Amos via Sam's tc-secrets release-keys and monitoring profiles; value applied manually before the dashboard existed. No secret values were read. TC-1161 D1 parity remains pending Sam's card. Every authorized deployment must prove this full ID with positive usage; a quota GET echo is not existence evidence. Existing node/billing authority may never be silently overridden." + "limit_bytes": 1073741824, + "_comment": "Billing-mode FLOOR, verified read-only after each authorized deploy: billing /api/admin/storage-comp storage_limit_bytes must be >= this floor and node override_bytes must be null. Value from internal D1 quota_overrides (secrets 1073741824, set by Sam via /storage 2026-10-17T05:36:53Z), migrated to a billing comp via /storage (TC-1162/TC-1164). Merge only after that migration is verified." } } } diff --git a/scripts/ci/reconcile-quota.py b/scripts/ci/reconcile-quota.py index d5eab63d..99b142ad 100755 --- a/scripts/ci/reconcile-quota.py +++ b/scripts/ci/reconcile-quota.py @@ -11,7 +11,7 @@ CONFIG_PATH = Path("ops/quota-overrides.json") OWNER = "tinycloud:pkh:eip155:1:0xd559CCd9EB87c530A9a349262669386dE93cf412" -LIMITS = {"applications": 5368709120, "secrets": 268721121} +LIMITS = {"applications": 5368709120, "secrets": 1073741824} NODE_HOST = "node.tinycloud.xyz" @@ -152,7 +152,7 @@ def reconcile(authority, overrides, node_secret, billing_secret, billing_origin) or actual["override_bytes"] != limit or type(actual.get("effective_limit_bytes")) is not int or actual["effective_limit_bytes"] != limit): raise QuotaError("quota override and effective limit did not both verify") - return "Quota overrides verified: applications=5368709120; secrets=268721121." + return "Quota overrides verified: " + "; ".join(f"{name}={limit}" for name, limit in LIMITS.items()) + "." for space, floor in overrides.items(): comp = comps[space] if (comp is None or not comp["active"] or type(comp["storage_limit_bytes"]) is not int diff --git a/scripts/ci/test-quota-authority.py b/scripts/ci/test-quota-authority.py index bdc26c7b..8b0998f3 100755 --- a/scripts/ci/test-quota-authority.py +++ b/scripts/ci/test-quota-authority.py @@ -17,7 +17,7 @@ exec(compile(SCRIPT.read_text(), str(SCRIPT), "exec"), NS) OWNER = "tinycloud:pkh:eip155:1:0xd559CCd9EB87c530A9a349262669386dE93cf412" -LIMITS = {OWNER + ":applications": 5368709120, OWNER + ":secrets": 268721121} +LIMITS = {OWNER + ":applications": 5368709120, OWNER + ":secrets": 1073741824} CANARIES = [] @@ -333,6 +333,32 @@ def test_checked_in_full_target_and_value_contract(self): self.assertIn(authority, ("node-override", "billing")) self.assertTrue(overrides == LIMITS, "Canonical Sam targets/values changed") + def test_shipped_billing_config_reconciles_against_exact_floors(self): + shipped = ROOT / "ops/quota-overrides.json" + document = json.loads(shipped.read_text()) + self.assertEqual(document["authority"], "billing") + self.billing_active() + for space, limit in LIMITS.items(): + self.billing_body[space]["storage_limit_bytes"] = limit + with patch.dict(NS, {"CONFIG_PATH": shipped}): + code, logs = self.run_main() + self.assertEqual(code, 0) + self.assertIn("billing-authoritative", logs) + self.assertEqual(self.puts(), []) + secrets_space = OWNER + ":secrets" + self.billing_body[secrets_space]["storage_limit_bytes"] = 1073741823 + code, logs = self.run_main() + self.assertEqual(code, 1) + self.assertIn("billing authority does not cover both reviewed quota floors", logs) + self.assertEqual(self.puts(), []) + self.billing_body[secrets_space]["storage_limit_bytes"] = 1073741824 + document["authority"] = "node-override" + self.config.write_text(json.dumps(document)) + code, logs = self.run_main() + self.assertEqual(code, 1) + self.assertIn("authority mismatch: flip to billing", logs) + self.assertEqual(self.puts(), []) + def test_missing_node_secret_is_preflight_failure(self): self.environment.pop("QUOTA_ADMIN_SECRET") self.assertEqual(self.run_main(["--preflight"])[0], 1)