You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/cloudflare-provisioning-api.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -14,6 +14,7 @@ The Worker compares SHA-256 token digests and never accepts plaintext API creden
14
14
15
15
## Resources
16
16
17
+
-`PUT /v1/artifacts/{sha256}` requires `Authorization: Bearer ...` with `sites:create`. Its body is the canonical `blocks-engine/php-transformer/site-artifact/v1` JSON artifact. The Worker enforces the artifact byte, file, path, encoding, and digest bounds before an immutable conditional write, then returns the exact reference accepted by site creation. Replays of identical bytes converge; conflicting content at the digest-addressed key fails closed.
17
18
-`POST /v1/sites` requires `Authorization: Bearer ...` with `sites:create` and `Idempotency-Key`. Its body is `wp-codebox/provisioning-create-request/v1`; it references an immutable staged artifact at `sites/provisioning/import-artifacts/<sha256>.json`. The Worker verifies the bounded artifact before allocating a site, then copies it immutably to the selected site namespace.
18
19
-`GET /v1/sites/{siteId}` requires `sites:read`.
19
20
-`POST /v1/sites/{siteId}/imports` requires `sites:import` and uses the existing bounded static-artifact request.
functioncount(db: Db,table: string){constexists=db.sqlite.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?").get(table);returnexists ? Number((db.sqlite.prepare(`SELECT COUNT(*) AS count FROM ${table}`).get()as{count: number}).count) : 0}
33
34
@@ -39,6 +40,33 @@ test("auth failures, malformed config, expiry, and scope stop before body and R2
39
40
test("invalid, missing, and oversized artifacts create zero allocations",async()=>{
test("registered active contexts are excluded",async()=>{constr=runtime();awaitr.operations.createOrConverge({id: "alpha",hostname: "alpha.example",origin: "https://alpha.example"},{idempotencyKey: "legacy",fingerprint: "x",artifact: {r2Key: "x",sha256: digest,size: artifact.byteLength},options: {slug: "x",name: "x",siteTitle: "x"}});constbody=await(awaitcreate(r)).json()as{site: {id: string}};assert.equal(body.site.id,"beta")})
43
71
test("exact and concurrent same-key creates converge",async()=>{constr=runtime();const[one,two]=awaitPromise.all([create(r),create(r)]);assert.equal(one.status,202);assert.deepEqual(awaitone.json(),awaittwo.json());assert.equal(count(r.db,"wp_codebox_api_sites"),1)})
44
72
test("changed fingerprints conflict without another allocation",async()=>{constr=runtime();awaitcreate(r);constresponse=awaitrouteProvisioningApi(createRequest("create-1",{title: "Changed"}),r.env,r.operations);assert.equal(response.status,409);assert.equal(count(r.db,"wp_codebox_api_sites"),1)})
@@ -51,7 +79,7 @@ test("cross-principal and site-restricted reads and imports fail closed", async
51
79
test("not-ready import is rejected and ready exact replay converges with an API link",async()=>{constr=runtime();constbody=await(awaitcreate(r)).json()as{site: {id: string;operation: string}};consturl=`https://control.invalid/v1/sites/${body.site.id}/imports`;constimportBody={schema: STATIC_ARTIFACT_IMPORT_REQUEST_SCHEMA,idempotencyKey: "import-1",artifact: {r2Key: `sites/${body.site.id}/import-artifacts/${digest}.json`,sha256: digest,size: artifact.byteLength},import: {slug: "import",name: "Import",siteTitle: "Import"}};constpending=awaitrouteProvisioningApi(newRequest(url,{method: "POST",headers: {authorization: "Bearer good","idempotency-key": "import-1"},body: JSON.stringify(importBody)}),r.env,r.operations);assert.equal(pending.status,409);r.db.sqlite.prepare("UPDATE wp_codebox_operations SET state = 'succeeded' WHERE site_id = ?").run(body.site.id);constone=awaitrouteProvisioningApi(newRequest(url,{method: "POST",headers: {authorization: "Bearer good","idempotency-key": "import-1"},body: JSON.stringify(importBody)}),r.env,r.operations);consttwo=awaitrouteProvisioningApi(newRequest(url,{method: "POST",headers: {authorization: "Bearer good","idempotency-key": "import-1"},body: JSON.stringify(importBody)}),r.env,r.operations);assert.deepEqual(awaitone.json(),awaittwo.json());assert.equal(count(r.db,"wp_codebox_api_operation_links"),2)})
0 commit comments