@pithy-sh/core 0.10.0 → 0.12.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/dist/access/access.d.ts +172 -0
- package/dist/access/access.d.ts.map +1 -0
- package/dist/access/access.js +147 -0
- package/dist/access/acting.d.ts +49 -0
- package/dist/access/acting.d.ts.map +1 -0
- package/dist/access/acting.js +21 -0
- package/dist/access/policyCheck.d.ts +33 -0
- package/dist/access/policyCheck.d.ts.map +1 -0
- package/dist/access/policyCheck.js +48 -0
- package/dist/access/usage.d.ts +83 -0
- package/dist/access/usage.d.ts.map +1 -0
- package/dist/access/usage.js +104 -0
- package/dist/access/visibility.d.ts +66 -0
- package/dist/access/visibility.d.ts.map +1 -0
- package/dist/access/visibility.js +86 -0
- package/dist/audit/auditEvent.d.ts +5 -0
- package/dist/audit/auditEvent.d.ts.map +1 -1
- package/dist/audit/auditEvent.js +2 -0
- package/dist/audit/recorder.d.ts +10 -2
- package/dist/audit/recorder.d.ts.map +1 -1
- package/dist/capability/bindings.d.ts +47 -2
- package/dist/capability/bindings.d.ts.map +1 -1
- package/dist/capability/bindings.js +117 -7
- package/dist/capability/capability.d.ts +110 -28
- package/dist/capability/capability.d.ts.map +1 -1
- package/dist/capability/capability.js +2 -0
- package/dist/capability/manifest.d.ts +2 -1
- package/dist/capability/manifest.d.ts.map +1 -1
- package/dist/capability/manifest.js +1 -1
- package/dist/capability/purge.d.ts +80 -0
- package/dist/capability/purge.d.ts.map +1 -0
- package/dist/capability/purge.js +76 -0
- package/dist/capability/settings.d.ts +86 -2
- package/dist/capability/settings.d.ts.map +1 -1
- package/dist/capability/settings.js +80 -1
- package/dist/cli/commandCatalog.generated.d.ts +238 -24
- package/dist/cli/commandCatalog.generated.d.ts.map +1 -1
- package/dist/cli/commandCatalog.generated.js +251 -22
- package/dist/cli/commandFacts.d.ts +2 -1
- package/dist/cli/commandFacts.d.ts.map +1 -1
- package/dist/cli/commandFacts.js +2 -0
- package/dist/controlPlane/capability.d.ts.map +1 -1
- package/dist/controlPlane/capability.js +19 -2
- package/dist/controlPlane/context.d.ts +5 -0
- package/dist/controlPlane/context.d.ts.map +1 -1
- package/dist/controlPlane/context.js +3 -1
- package/dist/controlPlane/data/connection.d.ts +49 -12
- package/dist/controlPlane/data/connection.d.ts.map +1 -1
- package/dist/controlPlane/data/connection.js +56 -2
- package/dist/controlPlane/discovery/adminRoute.d.ts +29 -0
- package/dist/controlPlane/discovery/adminRoute.d.ts.map +1 -1
- package/dist/controlPlane/discovery/adminRoute.js +3 -0
- package/dist/controlPlane/error/errors.d.ts +4 -3
- package/dist/controlPlane/error/errors.d.ts.map +1 -1
- package/dist/controlPlane/http/cors.d.ts +4 -4
- package/dist/controlPlane/http/cors.js +4 -4
- package/dist/controlPlane/http/guard.d.ts +11 -0
- package/dist/controlPlane/http/guard.d.ts.map +1 -1
- package/dist/controlPlane/http/guard.js +17 -1
- package/dist/controlPlane/http/handlers.d.ts +139 -0
- package/dist/controlPlane/http/handlers.d.ts.map +1 -1
- package/dist/controlPlane/http/handlers.js +67 -4
- package/dist/controlPlane/http/readiness.d.ts +33 -0
- package/dist/controlPlane/http/readiness.d.ts.map +1 -0
- package/dist/controlPlane/http/readiness.js +39 -0
- package/dist/controlPlane/http/responses.d.ts +245 -0
- package/dist/controlPlane/http/responses.d.ts.map +1 -1
- package/dist/controlPlane/http/responses.js +101 -4
- package/dist/controlPlane/http/routes.d.ts +2 -0
- package/dist/controlPlane/http/routes.d.ts.map +1 -1
- package/dist/controlPlane/http/routes.js +31 -3
- package/dist/controlPlane/http/verify.d.ts.map +1 -1
- package/dist/controlPlane/http/verify.js +2 -1
- package/dist/controlPlane/migrationState/migrationState.d.ts +102 -0
- package/dist/controlPlane/migrationState/migrationState.d.ts.map +1 -0
- package/dist/controlPlane/migrationState/migrationState.js +142 -0
- package/dist/controlPlane/migrations/0003_connection_principal.d.ts +21 -0
- package/dist/controlPlane/migrations/0003_connection_principal.d.ts.map +1 -0
- package/dist/controlPlane/migrations/0003_connection_principal.js +33 -0
- package/dist/controlPlane/scope/scope.d.ts +23 -2
- package/dist/controlPlane/scope/scope.d.ts.map +1 -1
- package/dist/controlPlane/scope/scope.js +24 -3
- package/dist/createBackend.d.ts.map +1 -1
- package/dist/createBackend.js +9 -2
- package/dist/createEntrypoint.d.ts.map +1 -1
- package/dist/createEntrypoint.js +5 -3
- package/dist/crypto/envelope.d.ts +86 -0
- package/dist/crypto/envelope.d.ts.map +1 -0
- package/dist/crypto/envelope.js +129 -0
- package/dist/crypto/fieldKeys.d.ts +41 -0
- package/dist/crypto/fieldKeys.d.ts.map +1 -0
- package/dist/crypto/fieldKeys.js +56 -0
- package/dist/data/codecs.d.ts +23 -10
- package/dist/data/codecs.d.ts.map +1 -1
- package/dist/data/codecs.js +50 -36
- package/dist/entitlement/allowance.d.ts +25 -0
- package/dist/entitlement/allowance.d.ts.map +1 -0
- package/dist/entitlement/allowance.js +80 -0
- package/dist/entitlement/entitlement.d.ts +41 -0
- package/dist/entitlement/entitlement.d.ts.map +1 -1
- package/dist/entitlement/meter.d.ts +57 -0
- package/dist/entitlement/meter.d.ts.map +1 -0
- package/dist/entitlement/meter.js +13 -0
- package/dist/error/extend.d.ts +6 -5
- package/dist/error/extend.d.ts.map +1 -1
- package/dist/error/http.d.ts +168 -0
- package/dist/error/http.d.ts.map +1 -1
- package/dist/error/payload.d.ts +336 -0
- package/dist/error/payload.d.ts.map +1 -1
- package/dist/error/payload.js +116 -4
- package/dist/error/pithyError.d.ts +18 -7
- package/dist/error/pithyError.d.ts.map +1 -1
- package/dist/error/pithyError.js +6 -0
- package/dist/http/authContext.d.ts +7 -0
- package/dist/http/authContext.d.ts.map +1 -1
- package/dist/http/authContext.js +8 -1
- package/dist/http/scopeGates.d.ts +20 -0
- package/dist/http/scopeGates.d.ts.map +1 -0
- package/dist/http/scopeGates.js +36 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/logger/logger.d.ts +12 -5
- package/dist/logger/logger.d.ts.map +1 -1
- package/dist/logger/record.d.ts +98 -0
- package/dist/logger/record.d.ts.map +1 -1
- package/dist/migrations/capabilitySets.d.ts +23 -0
- package/dist/migrations/capabilitySets.d.ts.map +1 -0
- package/dist/migrations/capabilitySets.js +74 -0
- package/dist/migrations/registry.d.ts +26 -0
- package/dist/migrations/registry.d.ts.map +1 -1
- package/dist/migrations/registry.js +38 -7
- package/dist/migrations/state.d.ts +60 -0
- package/dist/migrations/state.d.ts.map +1 -0
- package/dist/migrations/state.js +46 -0
- package/dist/naming/feature.d.ts +27 -5
- package/dist/naming/feature.d.ts.map +1 -1
- package/dist/naming/feature.js +36 -6
- package/dist/naming/limits.d.ts +47 -3
- package/dist/naming/limits.d.ts.map +1 -1
- package/dist/naming/limits.js +47 -3
- package/dist/naming/provisionScope.d.ts +6 -0
- package/dist/naming/provisionScope.d.ts.map +1 -1
- package/dist/naming/provisionScope.js +8 -3
- package/dist/naming/resourceNames.d.ts +21 -2
- package/dist/naming/resourceNames.d.ts.map +1 -1
- package/dist/naming/resourceNames.js +21 -3
- package/dist/privacy/blindIndex.d.ts +27 -0
- package/dist/privacy/blindIndex.d.ts.map +1 -0
- package/dist/privacy/blindIndex.js +57 -0
- package/dist/privacy/classes.d.ts +142 -0
- package/dist/privacy/classes.d.ts.map +1 -0
- package/dist/privacy/classes.js +209 -0
- package/dist/privacy/classify.d.ts +336 -0
- package/dist/privacy/classify.d.ts.map +1 -0
- package/dist/privacy/classify.js +1024 -0
- package/dist/privacy/encrypted.d.ts +210 -0
- package/dist/privacy/encrypted.d.ts.map +1 -0
- package/dist/privacy/encrypted.js +350 -0
- package/dist/privacy/encryptedColumns.d.ts +64 -0
- package/dist/privacy/encryptedColumns.d.ts.map +1 -0
- package/dist/privacy/encryptedColumns.js +134 -0
- package/dist/privacy/fieldRotation.d.ts +34 -0
- package/dist/privacy/fieldRotation.d.ts.map +1 -0
- package/dist/privacy/fieldRotation.js +186 -0
- package/dist/privacy/inventory.d.ts +12 -0
- package/dist/privacy/inventory.d.ts.map +1 -0
- package/dist/privacy/inventory.js +154 -0
- package/dist/privacy/posture.d.ts +114 -0
- package/dist/privacy/posture.d.ts.map +1 -0
- package/dist/privacy/posture.js +136 -0
- package/dist/privacy/redact.d.ts +7 -0
- package/dist/privacy/redact.d.ts.map +1 -0
- package/dist/privacy/redact.js +404 -0
- package/dist/privacy/report.d.ts +58 -0
- package/dist/privacy/report.d.ts.map +1 -0
- package/dist/privacy/report.js +15 -0
- package/dist/privacy/retirement.d.ts +68 -0
- package/dist/privacy/retirement.d.ts.map +1 -0
- package/dist/privacy/retirement.js +72 -0
- package/dist/privacy/sealed.d.ts +87 -0
- package/dist/privacy/sealed.d.ts.map +1 -0
- package/dist/privacy/sealed.js +221 -0
- package/dist/privacy/types.d.ts +559 -0
- package/dist/privacy/types.d.ts.map +1 -0
- package/dist/privacy/types.js +2 -0
- package/dist/seed/writeD1.d.ts +7 -1
- package/dist/seed/writeD1.d.ts.map +1 -1
- package/dist/seed/writeD1.js +9 -3
- package/dist/seed/writeKv.d.ts +2 -0
- package/dist/seed/writeKv.d.ts.map +1 -1
- package/dist/seed/writeKv.js +6 -2
- package/dist/version.generated.d.ts +1 -1
- package/dist/version.generated.js +1 -1
- package/dist/worker/serviceLoopback.d.ts +36 -0
- package/dist/worker/serviceLoopback.d.ts.map +1 -0
- package/dist/worker/serviceLoopback.js +74 -0
- package/dist/workflow/faults.d.ts +12 -1
- package/dist/workflow/faults.d.ts.map +1 -1
- package/dist/workflow/faults.js +22 -15
- package/package.json +2 -2
- package/src/access/access.ts +298 -0
- package/src/access/acting.ts +59 -0
- package/src/access/policyCheck.ts +77 -0
- package/src/access/usage.ts +141 -0
- package/src/access/visibility.ts +109 -0
- package/src/audit/auditEvent.ts +4 -0
- package/src/audit/recorder.ts +10 -2
- package/src/capability/bindings.ts +159 -13
- package/src/capability/capability.ts +114 -29
- package/src/capability/purge.ts +124 -0
- package/src/capability/settings.ts +146 -2
- package/src/cli/commandCatalog.generated.ts +271 -22
- package/src/cli/commandFacts.ts +2 -0
- package/src/controlPlane/capability.ts +36 -1
- package/src/controlPlane/context.ts +4 -0
- package/src/controlPlane/data/connection.ts +90 -0
- package/src/controlPlane/discovery/adminRoute.ts +11 -0
- package/src/controlPlane/error/errors.ts +4 -3
- package/src/controlPlane/http/cors.ts +4 -4
- package/src/controlPlane/http/guard.ts +21 -0
- package/src/controlPlane/http/handlers.ts +98 -4
- package/src/controlPlane/http/readiness.ts +50 -0
- package/src/controlPlane/http/responses.ts +240 -2
- package/src/controlPlane/http/routes.ts +55 -1
- package/src/controlPlane/http/verify.ts +2 -0
- package/src/controlPlane/migrationState/migrationState.ts +200 -0
- package/src/controlPlane/migrations/0003_connection_principal.ts +37 -0
- package/src/controlPlane/scope/scope.ts +25 -2
- package/src/controlPlane/token/base64url.ts +1 -1
- package/src/createBackend.ts +28 -6
- package/src/createEntrypoint.ts +9 -3
- package/src/crypto/envelope.ts +196 -0
- package/src/crypto/fieldKeys.ts +76 -0
- package/src/data/codecs.ts +69 -37
- package/src/entitlement/allowance.ts +85 -0
- package/src/entitlement/entitlement.ts +38 -0
- package/src/entitlement/meter.ts +69 -0
- package/src/error/extend.ts +6 -5
- package/src/error/payload.ts +253 -4
- package/src/error/pithyError.ts +21 -7
- package/src/http/authContext.ts +13 -1
- package/src/http/scopeGates.ts +34 -0
- package/src/index.ts +2 -0
- package/src/logger/logger.ts +12 -5
- package/src/migrations/capabilitySets.ts +87 -0
- package/src/migrations/registry.ts +46 -2
- package/src/migrations/state.ts +94 -0
- package/src/naming/feature.ts +46 -7
- package/src/naming/limits.ts +35 -3
- package/src/naming/provisionScope.ts +19 -1
- package/src/naming/resourceNames.ts +52 -5
- package/src/privacy/blindIndex.ts +81 -0
- package/src/privacy/classes.ts +277 -0
- package/src/privacy/classify.ts +1447 -0
- package/src/privacy/encrypted.ts +513 -0
- package/src/privacy/encryptedColumns.ts +185 -0
- package/src/privacy/fieldRotation.ts +234 -0
- package/src/privacy/inventory.ts +147 -0
- package/src/privacy/posture.ts +205 -0
- package/src/privacy/redact.ts +423 -0
- package/src/privacy/report.ts +64 -0
- package/src/privacy/retirement.ts +102 -0
- package/src/privacy/sealed.ts +323 -0
- package/src/privacy/types.ts +804 -0
- package/src/seed/writeD1.ts +13 -4
- package/src/seed/writeKv.ts +6 -2
- package/src/version.generated.ts +1 -1
- package/src/worker/serviceLoopback.ts +105 -0
- package/src/workflow/faults.ts +51 -24
package/dist/naming/limits.d.ts
CHANGED
|
@@ -123,6 +123,47 @@ export declare const NAMESPACE_LIMITS: {
|
|
|
123
123
|
readonly policy: "truncate";
|
|
124
124
|
readonly source: "cloudflare";
|
|
125
125
|
};
|
|
126
|
+
/**
|
|
127
|
+
* A Queue name: **1 to 63 characters**, lowercase letters, digits and dashes, starting and ending with a letter
|
|
128
|
+
* or number ([Queues · Get started](https://developers.cloudflare.com/queues/get-started/), verified
|
|
129
|
+
* 2026-10-18). Truncated rather than refused: Pithy recomputes a queue's name from its binding on every run,
|
|
130
|
+
* as it does a bucket's, so a deterministic hash is safe (#662). The same 63 as R2, so a feature's queue fits
|
|
131
|
+
* the shape {@link FEATURE_DERIVED_PROJECT_NAME} is derived against and moves no budget.
|
|
132
|
+
*/
|
|
133
|
+
readonly queue: {
|
|
134
|
+
readonly label: "a Queue name";
|
|
135
|
+
readonly maxLength: 63;
|
|
136
|
+
readonly minLength: 1;
|
|
137
|
+
readonly policy: "truncate";
|
|
138
|
+
readonly source: "cloudflare";
|
|
139
|
+
};
|
|
140
|
+
/**
|
|
141
|
+
* An Artifacts namespace: **2 to 63 characters**, starting with a letter or digit, the rest letters, digits, `.`,
|
|
142
|
+
* `_` and `-` ([Artifacts · Limits](https://developers.cloudflare.com/artifacts/platform/limits/), verified
|
|
143
|
+
* 2026-10-18). Truncated rather than refused: the kit derives it from the project and the environment on every
|
|
144
|
+
* run, like an R2 bucket name, and the longest project and environment compose 34 characters, so it never is (#673).
|
|
145
|
+
*/
|
|
146
|
+
readonly artifactsNamespace: {
|
|
147
|
+
readonly label: "an Artifacts namespace name";
|
|
148
|
+
readonly maxLength: 63;
|
|
149
|
+
readonly minLength: 2;
|
|
150
|
+
readonly policy: "truncate";
|
|
151
|
+
readonly source: "cloudflare";
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* An Artifacts repo name. **The charset is Cloudflare's** — a letter or digit, then letters, digits, `.`, `_` and
|
|
155
|
+
* `-` ([Artifacts · Limits](https://developers.cloudflare.com/artifacts/platform/limits/), verified 2026-10-18) —
|
|
156
|
+
* and **the length is ours**: that page states one for a namespace and none for a repo, so 2 to 63 mirrors the
|
|
157
|
+
* namespace rather than inventing a second number. Refused, never truncated: a repo name is either a UUID or a
|
|
158
|
+
* name somebody chose, and a name somebody chose is never silently shortened (#673).
|
|
159
|
+
*/
|
|
160
|
+
readonly artifactsRepo: {
|
|
161
|
+
readonly label: "an Artifacts repo name";
|
|
162
|
+
readonly maxLength: 63;
|
|
163
|
+
readonly minLength: 2;
|
|
164
|
+
readonly policy: "refuse";
|
|
165
|
+
readonly source: "pithy";
|
|
166
|
+
};
|
|
126
167
|
/**
|
|
127
168
|
* A D1 database name: `^[a-zA-Z0-9][a-zA-Z0-9_-]*$` in the OpenAPI schema, and **no documented
|
|
128
169
|
* length cap** — the limits page has no row for it. So the ceiling here is {@link MAX_PITHY_NAME}.
|
|
@@ -211,7 +252,10 @@ export declare const FEATURE_TAIL_SEPARATOR = "--";
|
|
|
211
252
|
* and teardown recomputes the name rather than matching a prefix.
|
|
212
253
|
*/
|
|
213
254
|
export declare const MIN_VERBATIM_BINDING = 12;
|
|
214
|
-
/**
|
|
255
|
+
/**
|
|
256
|
+
* The longest feature resource kind segment — `d1`, `kv`, `r2`, and a queue's `q` (#662). `feature.test.ts` pins
|
|
257
|
+
* every kind's `FEATURE_KIND_SEGMENT` to it, so a longer segment fails rather than shrinking every project's budget.
|
|
258
|
+
*/
|
|
215
259
|
export declare const MAX_FEATURE_KIND = 2;
|
|
216
260
|
/**
|
|
217
261
|
* What the longest Workflow name leaves a project.
|
|
@@ -229,7 +273,7 @@ export declare const MAX_FEATURE_KIND = 2;
|
|
|
229
273
|
export declare const WORKFLOW_DERIVED_PROJECT_NAME: number;
|
|
230
274
|
/**
|
|
231
275
|
* What the longest feature resource name leaves a project — `<project>-f<issue>-<slug>--<binding>-<kind>`,
|
|
232
|
-
* against R2's 63 (the strictest of the
|
|
276
|
+
* against R2's 63 (the strictest of the kinds a feature provisions, a queue's number too, and the same number a
|
|
233
277
|
* feature Worker script gets).
|
|
234
278
|
*
|
|
235
279
|
* ```
|
|
@@ -238,7 +282,7 @@ export declare const WORKFLOW_DERIVED_PROJECT_NAME: number;
|
|
|
238
282
|
* - 6 the issue number, six digits — `f999999` (MAX_ISSUE_DIGITS)
|
|
239
283
|
* - 12 `-` + a legible slug (MIN_LEGIBLE_SLUG)
|
|
240
284
|
* - 14 `--` + a binding kept whole (FEATURE_TAIL_SEPARATOR, MIN_VERBATIM_BINDING)
|
|
241
|
-
* - 3 `-` + the kind, `d1` | `kv` | `r2`
|
|
285
|
+
* - 3 `-` + the kind, `d1` | `kv` | `r2` | `q`
|
|
242
286
|
* ----
|
|
243
287
|
* 26
|
|
244
288
|
* ```
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../../src/naming/limits.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;GAcG;AAEH,sFAAsF;AACtF,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,OAAO,CAAC;AAEjD;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEnD,8FAA8F;AAC9F,MAAM,WAAW,cAAc;IAC7B,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,kGAAkG;IAClG,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,4FAA4F;IAC5F,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,kEAAkE;IAClE,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,mEAAmE;IACnE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;CAC9B;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,MAAM,CAAC;AAElC;;;GAGG;AACH,eAAO,MAAM,gBAAgB;IAC3B;;;OAGG;;iBACS,KAAK,EAAE,iBAAiB;iBAAE,SAAS,EAAE,EAAE;iBAAE,SAAS,EAAE,CAAC;iBAAE,MAAM,EAAE,QAAQ;iBAAE,MAAM,EAAE,YAAY;;IACzG;;;;;;OAMG;;iBACO,KAAK,EAAE,sBAAsB;iBAAE,SAAS,EAAE,EAAE;iBAAE,SAAS,EAAE,CAAC;iBAAE,MAAM,EAAE,QAAQ;iBAAE,MAAM,EAAE,YAAY;;IAC5G;;;OAGG;;iBACG,KAAK,EAAE,mBAAmB;iBAAE,SAAS,EAAE,EAAE;iBAAE,SAAS,EAAE,CAAC;iBAAE,MAAM,EAAE,UAAU;iBAAE,MAAM,EAAE,YAAY;;IACvG;;;;OAIG;;iBAED,KAAK,EAAE,wBAAwB;iBAC/B,SAAS,EAAE,EAAE;iBACb,SAAS,EAAE,CAAC;iBACZ,MAAM,EAAE,QAAQ;iBAChB,MAAM,EAAE,YAAY;;IAEtB;;;;;OAKG;;iBACG,KAAK,EAAE,sBAAsB;iBAAE,SAAS,EAAE,GAAG;iBAAE,SAAS,EAAE,CAAC;iBAAE,MAAM,EAAE,UAAU;iBAAE,MAAM,EAAE,YAAY;;IAC3G;;;OAGG;;iBACG,KAAK,EAAE,oBAAoB;iBAAE,SAAS;iBAAkB,SAAS,EAAE,CAAC;iBAAE,MAAM,EAAE,UAAU;iBAAE,MAAM,EAAE,OAAO;;IAC/G;;;OAGG;;iBAED,KAAK,EAAE,4BAA4B;iBACnC,SAAS;iBACT,SAAS,EAAE,CAAC;iBACZ,MAAM,EAAE,UAAU;iBAClB,MAAM,EAAE,OAAO;;IAEjB;;;OAGG;;iBAED,KAAK,EAAE,6BAA6B;iBACpC,SAAS;iBACT,SAAS,EAAE,CAAC;iBACZ,MAAM,EAAE,UAAU;iBAClB,MAAM,EAAE,OAAO;;CAEgC,CAAC;AAEpD,0DAA0D;AAC1D,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,gBAAgB,CAAC;AAEtD;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,QAAkC,CAAC;AAElE;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAElC;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAE3C;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAEvC
|
|
1
|
+
{"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../../src/naming/limits.ts"],"names":[],"mappings":"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"}
|
package/dist/naming/limits.js
CHANGED
|
@@ -80,6 +80,47 @@ const NAMESPACE_LIMITS = {
|
|
|
80
80
|
source: "cloudflare"
|
|
81
81
|
},
|
|
82
82
|
/**
|
|
83
|
+
* A Queue name: **1 to 63 characters**, lowercase letters, digits and dashes, starting and ending with a letter
|
|
84
|
+
* or number ([Queues · Get started](https://developers.cloudflare.com/queues/get-started/), verified
|
|
85
|
+
* 2026-10-18). Truncated rather than refused: Pithy recomputes a queue's name from its binding on every run,
|
|
86
|
+
* as it does a bucket's, so a deterministic hash is safe (#662). The same 63 as R2, so a feature's queue fits
|
|
87
|
+
* the shape {@link FEATURE_DERIVED_PROJECT_NAME} is derived against and moves no budget.
|
|
88
|
+
*/
|
|
89
|
+
queue: {
|
|
90
|
+
label: "a Queue name",
|
|
91
|
+
maxLength: 63,
|
|
92
|
+
minLength: 1,
|
|
93
|
+
policy: "truncate",
|
|
94
|
+
source: "cloudflare"
|
|
95
|
+
},
|
|
96
|
+
/**
|
|
97
|
+
* An Artifacts namespace: **2 to 63 characters**, starting with a letter or digit, the rest letters, digits, `.`,
|
|
98
|
+
* `_` and `-` ([Artifacts · Limits](https://developers.cloudflare.com/artifacts/platform/limits/), verified
|
|
99
|
+
* 2026-10-18). Truncated rather than refused: the kit derives it from the project and the environment on every
|
|
100
|
+
* run, like an R2 bucket name, and the longest project and environment compose 34 characters, so it never is (#673).
|
|
101
|
+
*/
|
|
102
|
+
artifactsNamespace: {
|
|
103
|
+
label: "an Artifacts namespace name",
|
|
104
|
+
maxLength: 63,
|
|
105
|
+
minLength: 2,
|
|
106
|
+
policy: "truncate",
|
|
107
|
+
source: "cloudflare"
|
|
108
|
+
},
|
|
109
|
+
/**
|
|
110
|
+
* An Artifacts repo name. **The charset is Cloudflare's** — a letter or digit, then letters, digits, `.`, `_` and
|
|
111
|
+
* `-` ([Artifacts · Limits](https://developers.cloudflare.com/artifacts/platform/limits/), verified 2026-10-18) —
|
|
112
|
+
* and **the length is ours**: that page states one for a namespace and none for a repo, so 2 to 63 mirrors the
|
|
113
|
+
* namespace rather than inventing a second number. Refused, never truncated: a repo name is either a UUID or a
|
|
114
|
+
* name somebody chose, and a name somebody chose is never silently shortened (#673).
|
|
115
|
+
*/
|
|
116
|
+
artifactsRepo: {
|
|
117
|
+
label: "an Artifacts repo name",
|
|
118
|
+
maxLength: 63,
|
|
119
|
+
minLength: 2,
|
|
120
|
+
policy: "refuse",
|
|
121
|
+
source: "pithy"
|
|
122
|
+
},
|
|
123
|
+
/**
|
|
83
124
|
* A D1 database name: `^[a-zA-Z0-9][a-zA-Z0-9_-]*$` in the OpenAPI schema, and **no documented
|
|
84
125
|
* length cap** — the limits page has no row for it. So the ceiling here is {@link MAX_PITHY_NAME}.
|
|
85
126
|
*/
|
|
@@ -165,7 +206,10 @@ const FEATURE_TAIL_SEPARATOR = "--";
|
|
|
165
206
|
* and teardown recomputes the name rather than matching a prefix.
|
|
166
207
|
*/
|
|
167
208
|
const MIN_VERBATIM_BINDING = 12;
|
|
168
|
-
/**
|
|
209
|
+
/**
|
|
210
|
+
* The longest feature resource kind segment — `d1`, `kv`, `r2`, and a queue's `q` (#662). `feature.test.ts` pins
|
|
211
|
+
* every kind's `FEATURE_KIND_SEGMENT` to it, so a longer segment fails rather than shrinking every project's budget.
|
|
212
|
+
*/
|
|
169
213
|
const MAX_FEATURE_KIND = 2;
|
|
170
214
|
/**
|
|
171
215
|
* What the longest Workflow name leaves a project.
|
|
@@ -183,7 +227,7 @@ const MAX_FEATURE_KIND = 2;
|
|
|
183
227
|
const WORKFLOW_DERIVED_PROJECT_NAME = NAMESPACE_LIMITS.workflow.maxLength - 1 - MAX_ENVIRONMENT_NAME - 1 - 22;
|
|
184
228
|
/**
|
|
185
229
|
* What the longest feature resource name leaves a project — `<project>-f<issue>-<slug>--<binding>-<kind>`,
|
|
186
|
-
* against R2's 63 (the strictest of the
|
|
230
|
+
* against R2's 63 (the strictest of the kinds a feature provisions, a queue's number too, and the same number a
|
|
187
231
|
* feature Worker script gets).
|
|
188
232
|
*
|
|
189
233
|
* ```
|
|
@@ -192,7 +236,7 @@ const WORKFLOW_DERIVED_PROJECT_NAME = NAMESPACE_LIMITS.workflow.maxLength - 1 -
|
|
|
192
236
|
* - 6 the issue number, six digits — `f999999` (MAX_ISSUE_DIGITS)
|
|
193
237
|
* - 12 `-` + a legible slug (MIN_LEGIBLE_SLUG)
|
|
194
238
|
* - 14 `--` + a binding kept whole (FEATURE_TAIL_SEPARATOR, MIN_VERBATIM_BINDING)
|
|
195
|
-
* - 3 `-` + the kind, `d1` | `kv` | `r2`
|
|
239
|
+
* - 3 `-` + the kind, `d1` | `kv` | `r2` | `q`
|
|
196
240
|
* ----
|
|
197
241
|
* 26
|
|
198
242
|
* ```
|
|
@@ -171,6 +171,12 @@ export interface ProvisionScope {
|
|
|
171
171
|
* `<project>-feature-email-send` would be one Workflow every open branch deployed over every other's.
|
|
172
172
|
*/
|
|
173
173
|
readonly workflowHost: Omit<WorkflowHostNameParts, "capability">;
|
|
174
|
+
/**
|
|
175
|
+
* The Artifacts namespace an `artifacts` binding names in this scope (#673): `<project>-<env>` in a declared
|
|
176
|
+
* environment, `<project>-f<issue>-<slug>--artifacts` in a feature. On the scope for the reason every other name
|
|
177
|
+
* is: the stanza a run writes and the namespace it writes into it are one decision.
|
|
178
|
+
*/
|
|
179
|
+
readonly artifactsNamespace: string;
|
|
174
180
|
}
|
|
175
181
|
/**
|
|
176
182
|
* The same branch, one line down, for a provisioned resource: a `global` binding resolves to the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provisionScope.d.ts","sourceRoot":"","sources":["../../src/naming/provisionScope.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAEhE,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,mBAAmB,
|
|
1
|
+
{"version":3,"file":"provisionScope.d.ts","sourceRoot":"","sources":["../../src/naming/provisionScope.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAEhE,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EAKzB,MAAM,WAAW,CAAC;AAInB;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG,aAAa,GAAG,QAAQ,CAAC;AAEvD;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,eAAe,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACxD,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;CAC1B;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,oBAAoB;IACnC,2GAA2G;IAC3G,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,oGAAoG;IACpG,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,uFAAuF;AACvF,MAAM,WAAW,cAAc;IAC7B,6FAA6F;IAC7F,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,EAAE,aAAa,GAAG,MAAM,CAAC;IACpF;;;;;;;;;OASG;IACH,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B;;;;;;;;;;OAUG;IACH,MAAM,CAAC,MAAM,EAAE,oBAAoB,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAChE;;;;;;;OAOG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,eAAe,GAAG,MAAM,CAAC;IAClE;;;;;;;;OAQG;IACH,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAC,qBAAqB,EAAE,YAAY,CAAC,CAAC;IACjE;;;;OAIG;IACH,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;CACrC;AAsBD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,mBAAmB,EACzB,MAAM,EAAE,mBAAmB,GAC1B,MAAM,CAAC;AACV,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,mBAAmB,EACzB,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAChC,MAAM,CAAC;AAsBV;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAKpE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,cAAc,CA+BrF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,eAAe,GAAG,cAAc,CAsBtE;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,eAAe,EAAE,MAAM,EAAE,oBAAoB,GAAG,MAAM,EAAE,CAY1G"}
|
|
@@ -4,14 +4,15 @@ import { InternalError, ValidationError } from "../error/pithyError.js";
|
|
|
4
4
|
import { commandName } from "../cli/command.js";
|
|
5
5
|
import { FEATURE_ENVIRONMENT, assertValidEnvironment, isFeatureMarker } from "./environment.js";
|
|
6
6
|
import { kebab } from "./resource.js";
|
|
7
|
-
import { featureResourceName, featureSecretEntryName, featureWorkerName } from "./feature.js";
|
|
7
|
+
import { featureArtifactsNamespace, featureResourceName, featureSecretEntryName, featureWorkerName } from "./feature.js";
|
|
8
8
|
import { resourceNames } from "./resourceNames.js";
|
|
9
9
|
//#region src/naming/provisionScope.ts
|
|
10
10
|
/** The wrangler binding array a resource kind's name is composed for. */
|
|
11
11
|
const KIND_NAMER = {
|
|
12
12
|
d1: "d1",
|
|
13
13
|
kv: "kv",
|
|
14
|
-
r2: "r2"
|
|
14
|
+
r2: "r2",
|
|
15
|
+
queue: "queue"
|
|
15
16
|
};
|
|
16
17
|
/**
|
|
17
18
|
* The one branch every scope shares: a `global` secret resolves to the project's single
|
|
@@ -102,7 +103,8 @@ function environmentScope(project, environment) {
|
|
|
102
103
|
workflowHost: {
|
|
103
104
|
project,
|
|
104
105
|
env: environment
|
|
105
|
-
}
|
|
106
|
+
},
|
|
107
|
+
artifactsNamespace: names.artifactsNamespace()
|
|
106
108
|
};
|
|
107
109
|
}
|
|
108
110
|
/**
|
|
@@ -145,6 +147,9 @@ function featureScope(identity) {
|
|
|
145
147
|
project: identity.project,
|
|
146
148
|
env: FEATURE_ENVIRONMENT,
|
|
147
149
|
feature: identity
|
|
150
|
+
},
|
|
151
|
+
get artifactsNamespace() {
|
|
152
|
+
return featureArtifactsNamespace(identity);
|
|
148
153
|
}
|
|
149
154
|
};
|
|
150
155
|
}
|
|
@@ -49,6 +49,8 @@ export interface ScopedNames {
|
|
|
49
49
|
kv(binding: string): string;
|
|
50
50
|
/** An R2 bucket. Cloudflare's 63 — the one namespace where that number was always right. */
|
|
51
51
|
r2(binding: string): string;
|
|
52
|
+
/** A Queue. Cloudflare's 63, truncated with a stable hash like a bucket (#662). */
|
|
53
|
+
queue(binding: string): string;
|
|
52
54
|
/** A Vectorize index. 64 bytes, refused rather than truncated: a renamed index has no vectors. */
|
|
53
55
|
vectorizeIndex(index: string): string;
|
|
54
56
|
/** A Secrets Store entry. No Cloudflare cap; Pithy's ceiling. */
|
|
@@ -56,22 +58,39 @@ export interface ScopedNames {
|
|
|
56
58
|
/** A Cloudflare API token label. No Cloudflare cap; Pithy's ceiling. */
|
|
57
59
|
apiToken(profile: string): string;
|
|
58
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* The names in one declared environment: everything a scope has, and the one name that exists per environment
|
|
63
|
+
* and never at `global`.
|
|
64
|
+
*/
|
|
65
|
+
export interface EnvironmentNames extends ScopedNames {
|
|
66
|
+
/**
|
|
67
|
+
* The Artifacts namespace — `<project>-<env>`, with no `<thing>` (#673). One per environment, so a feature's
|
|
68
|
+
* repos never sit beside production's and the per-namespace rate limit splits per environment. There is no
|
|
69
|
+
* global one, because a namespace shared across environments is exactly that mix.
|
|
70
|
+
*/
|
|
71
|
+
artifactsNamespace(): string;
|
|
72
|
+
}
|
|
59
73
|
/** The names a feature environment provisions under, with the project already bound. */
|
|
60
74
|
export interface FeatureNames {
|
|
61
|
-
/** A feature's D1, KV, or
|
|
75
|
+
/** A feature's D1, KV, R2 or Queue resource — `<project>-f<issue>-<slug>--<binding>-<kind>`. */
|
|
62
76
|
resource(binding: string, kind: FeatureResourceKind): string;
|
|
63
77
|
/**
|
|
64
78
|
* A feature's Worker script — `<project>-f<issue>-<slug>-<app>`, from the `apps/<app>` directory and
|
|
65
79
|
* never the deploy name, which already leads with the project (#587).
|
|
66
80
|
*/
|
|
67
81
|
worker(app: string): string;
|
|
82
|
+
/**
|
|
83
|
+
* A feature's Artifacts namespace — `<project>-f<issue>-<slug>--artifacts` (#673). The tail is what makes it a
|
|
84
|
+
* feature name `isFeatureOwnedName` reads back, so teardown reaps this feature's repos and no sibling's.
|
|
85
|
+
*/
|
|
86
|
+
artifactsNamespace(): string;
|
|
68
87
|
}
|
|
69
88
|
/** Everything a project can be asked to name. Created once, from the project, by {@link resourceNames}. */
|
|
70
89
|
export interface ProjectNames {
|
|
71
90
|
/** The kebabbed project name every name below leads with. */
|
|
72
91
|
readonly project: string;
|
|
73
92
|
/** The names in one environment. Throws if the environment is not one this scheme accepts. */
|
|
74
|
-
env(environment: string):
|
|
93
|
+
env(environment: string): EnvironmentNames;
|
|
75
94
|
/** The names shared by every environment — the `global` scope, without typing the word. */
|
|
76
95
|
readonly global: ScopedNames;
|
|
77
96
|
/** The names a feature environment provisions under. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resourceNames.d.ts","sourceRoot":"","sources":["../../src/naming/resourceNames.ts"],"names":[],"mappings":"AAMA,OAAO,
|
|
1
|
+
{"version":3,"file":"resourceNames.d.ts","sourceRoot":"","sources":["../../src/naming/resourceNames.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EAIzB,MAAM,WAAW,CAAC;AAInB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,8FAA8F;AAC9F,MAAM,WAAW,WAAW;IAC1B,sGAAsG;IACtG,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;IACnC,0GAA0G;IAC1G,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IAClD,uFAAuF;IACvF,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,kFAAkF;IAClF,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,4FAA4F;IAC5F,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,mFAAmF;IACnF,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,kGAAkG;IAClG,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACtC,iEAAiE;IACjE,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACpC,wEAAwE;IACxE,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;CACnC;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACnD;;;;OAIG;IACH,kBAAkB,IAAI,MAAM,CAAC;CAC9B;AAED,wFAAwF;AACxF,MAAM,WAAW,YAAY;IAC3B,gGAAgG;IAChG,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAAC;IAC7D;;;OAGG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B;;;OAGG;IACH,kBAAkB,IAAI,MAAM,CAAC;CAC9B;AAED,2GAA2G;AAC3G,MAAM,WAAW,YAAY;IAC3B,6DAA6D;IAC7D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,8FAA8F;IAC9F,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,gBAAgB,CAAC;IAC3C,2FAA2F;IAC3F,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,wDAAwD;IACxD,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,GAAG,YAAY,CAAC;CACnE;AA+ED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CAuB3D"}
|
|
@@ -4,7 +4,7 @@ import { InternalError, ValidationError } from "../error/pithyError.js";
|
|
|
4
4
|
import { GLOBAL_SCOPE, assertValidEnvironment } from "./environment.js";
|
|
5
5
|
import { NAMESPACE_LIMITS } from "./limits.js";
|
|
6
6
|
import { assertValidProjectName, kebab, resourceName } from "./resource.js";
|
|
7
|
-
import { featureResourceName, featureWorkerName } from "./feature.js";
|
|
7
|
+
import { featureArtifactsNamespace, featureResourceName, featureWorkerName } from "./feature.js";
|
|
8
8
|
import { workflowHostName, workflowScriptName } from "../workflow/naming.js";
|
|
9
9
|
//#region src/naming/resourceNames.ts
|
|
10
10
|
/**
|
|
@@ -49,6 +49,19 @@ function scopedName(project, scope, thing, limit) {
|
|
|
49
49
|
});
|
|
50
50
|
return name;
|
|
51
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* `<project>-<env>`, under the Artifacts namespace rule. The project and environment are both validated by now, and
|
|
54
|
+
* the longest of each compose 34 characters, so the cap is a check rather than a truncation that ever happens.
|
|
55
|
+
*/
|
|
56
|
+
function artifactsNamespaceName(project, environment) {
|
|
57
|
+
const limit = NAMESPACE_LIMITS.artifactsNamespace;
|
|
58
|
+
const name = `${project}-${environment}`;
|
|
59
|
+
if (name.length > limit.maxLength || name.length < limit.minLength) throw new InternalError({
|
|
60
|
+
message: `"${name}" does not fit ${limit.label}, which takes ${limit.minLength} to ${limit.maxLength} characters.`,
|
|
61
|
+
action: "Shorten the project or environment name."
|
|
62
|
+
});
|
|
63
|
+
return name;
|
|
64
|
+
}
|
|
52
65
|
/** The getters for one scope. `global` and every environment share this, so nothing special-cases either. */
|
|
53
66
|
function scopedNames(project, scope) {
|
|
54
67
|
return {
|
|
@@ -66,6 +79,7 @@ function scopedNames(project, scope) {
|
|
|
66
79
|
d1: (binding) => scopedName(project, scope, binding, NAMESPACE_LIMITS.d1),
|
|
67
80
|
kv: (binding) => scopedName(project, scope, binding, NAMESPACE_LIMITS.kv),
|
|
68
81
|
r2: (binding) => scopedName(project, scope, binding, NAMESPACE_LIMITS.r2),
|
|
82
|
+
queue: (binding) => scopedName(project, scope, binding, NAMESPACE_LIMITS.queue),
|
|
69
83
|
vectorizeIndex: (index) => scopedName(project, scope, index, NAMESPACE_LIMITS.vectorizeIndex),
|
|
70
84
|
secretEntry: (secret) => scopedName(project, scope, secret, NAMESPACE_LIMITS.secretEntry),
|
|
71
85
|
apiToken: (profile) => scopedName(project, scope, profile, NAMESPACE_LIMITS.apiToken)
|
|
@@ -85,7 +99,10 @@ function resourceNames(project) {
|
|
|
85
99
|
project: normalized,
|
|
86
100
|
env(environment) {
|
|
87
101
|
assertValidEnvironment(environment);
|
|
88
|
-
return
|
|
102
|
+
return {
|
|
103
|
+
...scopedNames(normalized, environment),
|
|
104
|
+
artifactsNamespace: () => artifactsNamespaceName(normalized, environment)
|
|
105
|
+
};
|
|
89
106
|
},
|
|
90
107
|
global: scopedNames(normalized, GLOBAL_SCOPE),
|
|
91
108
|
feature(identity) {
|
|
@@ -95,7 +112,8 @@ function resourceNames(project) {
|
|
|
95
112
|
};
|
|
96
113
|
return {
|
|
97
114
|
resource: (binding, kind) => featureResourceName(full, binding, kind),
|
|
98
|
-
worker: (app) => featureWorkerName(full, app)
|
|
115
|
+
worker: (app) => featureWorkerName(full, app),
|
|
116
|
+
artifactsNamespace: () => featureArtifactsNamespace(full)
|
|
99
117
|
};
|
|
100
118
|
}
|
|
101
119
|
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
import { type EncryptionConfig } from "../crypto/envelope";
|
|
4
|
+
import { type BlindIndexNormalizer } from "./encrypted";
|
|
5
|
+
/**
|
|
6
|
+
* **A blind index: a keyed hash an encrypted column can be found by** (#390).
|
|
7
|
+
*
|
|
8
|
+
* An encrypted column cannot answer `WHERE email = ?`. A sibling column holding `HMAC(key, normalize(value))` can,
|
|
9
|
+
* for equality and nothing else. One rule here is shared by the app Worker that seals, `sealed().match` that looks
|
|
10
|
+
* up, and the rotator that re-indexes inside the manager, so the three cannot hash one value two ways.
|
|
11
|
+
*
|
|
12
|
+
* - **The key is derived, on the field key's own version axis.** Each version's index key is HKDF-SHA256 over that
|
|
13
|
+
* version's field key, with the label `pithy/blind-index/<normalizer>`. One secret, one rotation.
|
|
14
|
+
* - **The value carries its version**: `<version>:<hmac>`, so the stale count reaches an index exactly as it reaches
|
|
15
|
+
* an envelope, by reading the prefix.
|
|
16
|
+
* - **The normalizer is in the label**, so changing a field's normalizer cannot silently miss against old hashes: they
|
|
17
|
+
* are hashes under a different key, and the change reads as a re-index.
|
|
18
|
+
*/
|
|
19
|
+
/** The HKDF label one normalizer's index keys are derived under. */
|
|
20
|
+
export declare function blindIndexLabel(normalizer: BlindIndexNormalizer): string;
|
|
21
|
+
/** The HMAC key for one version and normalizer: HKDF-SHA256 over that version's field key. */
|
|
22
|
+
export declare function blindIndexKey(config: EncryptionConfig, version: number, normalizer: BlindIndexNormalizer): Promise<CryptoKey>;
|
|
23
|
+
/** The blind index of `value` under `version`: `<version>:<hmac>`. The value is normalized first. */
|
|
24
|
+
export declare function blindIndexValue(config: EncryptionConfig, version: number, normalizer: BlindIndexNormalizer, value: string): Promise<string>;
|
|
25
|
+
/** The version a blind-index value was written under, or `null` for a value that is not one. */
|
|
26
|
+
export declare function blindIndexVersion(value: string): number | null;
|
|
27
|
+
//# sourceMappingURL=blindIndex.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blindIndex.d.ts","sourceRoot":"","sources":["../../src/privacy/blindIndex.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,gBAAgB,EAAY,MAAM,oBAAoB,CAAC;AAErE,OAAO,EAAE,KAAK,oBAAoB,EAAqB,MAAM,aAAa,CAAC;AAE3E;;;;;;;;;;;;;GAaG;AAEH,oEAAoE;AACpE,wBAAgB,eAAe,CAAC,UAAU,EAAE,oBAAoB,GAAG,MAAM,CAExE;AASD,8FAA8F;AAC9F,wBAAsB,aAAa,CACjC,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,oBAAoB,GAC/B,OAAO,CAAC,SAAS,CAAC,CAmBpB;AAED,qGAAqG;AACrG,wBAAsB,eAAe,CACnC,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,oBAAoB,EAChC,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,CAQjB;AAED,gGAAgG;AAChG,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG9D"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
import { keyBytes } from "../crypto/envelope.js";
|
|
4
|
+
import { FIELD_KEYS_BINDING } from "../crypto/fieldKeys.js";
|
|
5
|
+
import { normalizeForIndex } from "./encrypted.js";
|
|
6
|
+
//#region src/privacy/blindIndex.ts
|
|
7
|
+
/**
|
|
8
|
+
* **A blind index: a keyed hash an encrypted column can be found by** (#390).
|
|
9
|
+
*
|
|
10
|
+
* An encrypted column cannot answer `WHERE email = ?`. A sibling column holding `HMAC(key, normalize(value))` can,
|
|
11
|
+
* for equality and nothing else. One rule here is shared by the app Worker that seals, `sealed().match` that looks
|
|
12
|
+
* up, and the rotator that re-indexes inside the manager, so the three cannot hash one value two ways.
|
|
13
|
+
*
|
|
14
|
+
* - **The key is derived, on the field key's own version axis.** Each version's index key is HKDF-SHA256 over that
|
|
15
|
+
* version's field key, with the label `pithy/blind-index/<normalizer>`. One secret, one rotation.
|
|
16
|
+
* - **The value carries its version**: `<version>:<hmac>`, so the stale count reaches an index exactly as it reaches
|
|
17
|
+
* an envelope, by reading the prefix.
|
|
18
|
+
* - **The normalizer is in the label**, so changing a field's normalizer cannot silently miss against old hashes: they
|
|
19
|
+
* are hashes under a different key, and the change reads as a re-index.
|
|
20
|
+
*/
|
|
21
|
+
/** The HKDF label one normalizer's index keys are derived under. */
|
|
22
|
+
function blindIndexLabel(normalizer) {
|
|
23
|
+
return `pithy/blind-index/${normalizer}`;
|
|
24
|
+
}
|
|
25
|
+
/** Unpadded base64url, the alphabet a blind index is written in. */
|
|
26
|
+
function base64Url(bytes) {
|
|
27
|
+
let binary = "";
|
|
28
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
29
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
30
|
+
}
|
|
31
|
+
/** The HMAC key for one version and normalizer: HKDF-SHA256 over that version's field key. */
|
|
32
|
+
async function blindIndexKey(config, version, normalizer) {
|
|
33
|
+
const material = await crypto.subtle.importKey("raw", keyBytes(config, version, { keys: FIELD_KEYS_BINDING }), "HKDF", false, ["deriveBits"]);
|
|
34
|
+
const bits = await crypto.subtle.deriveBits({
|
|
35
|
+
name: "HKDF",
|
|
36
|
+
hash: "SHA-256",
|
|
37
|
+
salt: /* @__PURE__ */ new Uint8Array(0),
|
|
38
|
+
info: Uint8Array.from(new TextEncoder().encode(blindIndexLabel(normalizer)))
|
|
39
|
+
}, material, 256);
|
|
40
|
+
return crypto.subtle.importKey("raw", bits, {
|
|
41
|
+
name: "HMAC",
|
|
42
|
+
hash: "SHA-256"
|
|
43
|
+
}, false, ["sign"]);
|
|
44
|
+
}
|
|
45
|
+
/** The blind index of `value` under `version`: `<version>:<hmac>`. The value is normalized first. */
|
|
46
|
+
async function blindIndexValue(config, version, normalizer, value) {
|
|
47
|
+
const key = await blindIndexKey(config, version, normalizer);
|
|
48
|
+
const mac = await crypto.subtle.sign("HMAC", key, Uint8Array.from(new TextEncoder().encode(normalizeForIndex(normalizer, value))));
|
|
49
|
+
return `${version}:${base64Url(new Uint8Array(mac))}`;
|
|
50
|
+
}
|
|
51
|
+
/** The version a blind-index value was written under, or `null` for a value that is not one. */
|
|
52
|
+
function blindIndexVersion(value) {
|
|
53
|
+
const match = /^(\d+):/.exec(value);
|
|
54
|
+
return match ? Number(match[1]) : null;
|
|
55
|
+
}
|
|
56
|
+
//#endregion
|
|
57
|
+
export { blindIndexKey, blindIndexLabel, blindIndexValue, blindIndexVersion };
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
/**
|
|
5
|
+
* **A field declares its own privacy class, and the declaration drives everything downstream** (#132).
|
|
6
|
+
*
|
|
7
|
+
* One marker, several consumers — the shape `@pithy-sh/vector` already uses, where `.meta({ filterable: true
|
|
8
|
+
* })` drives provisioning, the filter type, the drift check and the boot check. Here the marker drives the
|
|
9
|
+
* type gate on the three internal surfaces (the logger, `AuditEvent.metadata`, `PithyError.detail`), the
|
|
10
|
+
* masked view `redact` returns, the classification `classifyPrivacy` derives, and the inventory the control
|
|
11
|
+
* plane reports.
|
|
12
|
+
*
|
|
13
|
+
* ## What a marker does, in one call
|
|
14
|
+
*
|
|
15
|
+
* `pii(schema)` does two things. It attaches `.meta({ privacy: "pii" })`, which is **introspectable** — that is
|
|
16
|
+
* what `redact`, `classifyPrivacy` and the inventory read. And it applies Zod's `.brand()`, which changes the
|
|
17
|
+
* **inferred type** — that is what makes a log call carrying the value fail to compile. The brand lands on the
|
|
18
|
+
* field, not on the object, so extracting the field does not launder it: `user.email` is as branded as `user`.
|
|
19
|
+
*
|
|
20
|
+
* **A marker over another marker adds its class.** `pii(secret(x))` and `secret(pii(x))` are the same field: it
|
|
21
|
+
* carries both classes, in its `meta` (as a list, strongest first) and in its type (both brands). It is masked with the
|
|
22
|
+
* strongest one's placeholder and listed once per class. The same marker twice is one class.
|
|
23
|
+
*
|
|
24
|
+
* **The brand key is `privacy:<class>`, not the bare class name.** An adopter's own `.brand<"pii">()` for some
|
|
25
|
+
* unrelated purpose must not trip a gate it never opted into, and an adopter's `UserId` brand must not either:
|
|
26
|
+
* the gate reads a brand under the `privacy:` namespace and nothing else, which is the federated-key rule
|
|
27
|
+
* (`auth/invalid_token`, `pithy_auth_users`) applied one more time.
|
|
28
|
+
*
|
|
29
|
+
* **Nothing at runtime changes.** Zod's `.brand()` returns the same schema object — the brand exists only in
|
|
30
|
+
* the type — and `.meta()` returns a clone that parses exactly as its source. `Schema.parse(row)` returns the
|
|
31
|
+
* same data it did before the marker, and no column is added anywhere.
|
|
32
|
+
*
|
|
33
|
+
* ## The set is open
|
|
34
|
+
*
|
|
35
|
+
* Four classes ship named — `secret`, `pii`, `phi`, `pci` — and {@link definePrivacyClass} registers more
|
|
36
|
+
* (`genetic`, `biometric`, whatever a regulator names) without a change to core. A closed union is what #117
|
|
37
|
+
* records the cost of, and a healthcare adopter should not have to wait on us.
|
|
38
|
+
*
|
|
39
|
+
* ## Where `secret` stops and `@pithy-sh/secrets` starts
|
|
40
|
+
*
|
|
41
|
+
* Two different facts, kept apart on purpose. `@pithy-sh/secrets` decides **where a credential the Worker reads
|
|
42
|
+
* is stored** — its registry names a backend, and its reader redacts the value it hands back. `secret()` says
|
|
43
|
+
* **what a field in a data shape is** — a receipt, a magic-link token, a session id, a key hash — values that
|
|
44
|
+
* live in rows and payloads and that no secrets registry ever holds. Merging them would make core depend on a
|
|
45
|
+
* capability (principle 4) and would make a storage decision answer a classification question.
|
|
46
|
+
*/
|
|
47
|
+
/** The `meta` key a marker writes and every reader reads. */
|
|
48
|
+
export declare const PRIVACY_META_KEY = "privacy";
|
|
49
|
+
/** The prefix of every privacy brand, so the gate never reads a brand that means something else. */
|
|
50
|
+
export declare const PRIVACY_BRAND_PREFIX = "privacy:";
|
|
51
|
+
/** A class name: a lowercase identifier. It becomes a brand key, a config value and a report column. */
|
|
52
|
+
export declare const PrivacyClassName: z.ZodString;
|
|
53
|
+
export type PrivacyClassName = z.output<typeof PrivacyClassName>;
|
|
54
|
+
/** The four classes the kit names, in the order every report lists them. */
|
|
55
|
+
export declare const BUILT_IN_PRIVACY_CLASSES: readonly ["secret", "pii", "phi", "pci"];
|
|
56
|
+
/** One of the four built-in class names. */
|
|
57
|
+
export type BuiltInPrivacyClass = (typeof BUILT_IN_PRIVACY_CLASSES)[number];
|
|
58
|
+
/** How a class masks a value: the string that stands in its place on every internal surface. */
|
|
59
|
+
export type PrivacyMask = (value: unknown) => string;
|
|
60
|
+
/** One registered class: its name, what it means, and how it masks. */
|
|
61
|
+
export interface PrivacyClass {
|
|
62
|
+
/** The class name — the `meta` value and the brand's suffix. */
|
|
63
|
+
readonly name: string;
|
|
64
|
+
/** What the class means, in one sentence an auditor reads. */
|
|
65
|
+
readonly description: string;
|
|
66
|
+
/** The masked form of a value of this class. */
|
|
67
|
+
readonly mask: PrivacyMask;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The brand a marker puts on a schema's output type. Zod's own brand machinery, under the `privacy:` key.
|
|
71
|
+
*
|
|
72
|
+
* `"out"` on purpose: the **input** side stays unbranded, so `z.input` — the SQLite row shape, the Kysely
|
|
73
|
+
* table type, a KV write's pre-parse value — is exactly what it was. A row read from D1 parses into the
|
|
74
|
+
* branded app shape, and `Schema.encode()` hands Kysely the plain row back.
|
|
75
|
+
*/
|
|
76
|
+
export type Marked<S extends z.ZodType, C extends string> = z.core.$ZodBranded<S, `${typeof PRIVACY_BRAND_PREFIX}${C}`, "out">;
|
|
77
|
+
/** A marker for one class: wraps a schema and returns it marked. Carries its class name for a reader. */
|
|
78
|
+
export interface PrivacyMarker<C extends string> {
|
|
79
|
+
<S extends z.ZodType>(schema: S): Marked<S, C>;
|
|
80
|
+
/** The class this marker applies. */
|
|
81
|
+
readonly className: C;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Mask a primary account number to its first six and last four digits — `424242******4242`.
|
|
85
|
+
*
|
|
86
|
+
* **The one class whose mask is not a placeholder, because the masked form is the useful one.** First-six and
|
|
87
|
+
* last-four is the display PCI-DSS permits, and it is what an operator reading a log needs to match a
|
|
88
|
+
* complaint to a card without holding the card. Spaces and dashes are separators and are dropped; anything
|
|
89
|
+
* that is not 13 to 19 digits once they are is not a card number, and masks to `[pci]` rather than to a
|
|
90
|
+
* partial reveal of something else.
|
|
91
|
+
*
|
|
92
|
+
* Every payment rail Pithy ships is hosted, so no PAN ever reaches an adopter's Worker through the kit. The
|
|
93
|
+
* class is here for the adopter's own schemas.
|
|
94
|
+
*/
|
|
95
|
+
export declare function maskPan(value: unknown): string;
|
|
96
|
+
/** The class a name refers to, or `undefined` for a name nothing registered. */
|
|
97
|
+
export declare function privacyClass(name: string): PrivacyClass | undefined;
|
|
98
|
+
/** Every registered class, built-ins first in their fixed order, then each adopter class in registration order. */
|
|
99
|
+
export declare function privacyClasses(): PrivacyClass[];
|
|
100
|
+
/**
|
|
101
|
+
* `names` from the strongest to the weakest, each once: `secret`, then `phi`, then `pci`, then each adopter class, then
|
|
102
|
+
* `pii`. An adopter registers a class because its data is more specific than `pii`, so it ranks above it; adopter
|
|
103
|
+
* classes rank among themselves by name. The order a marker records several classes in, whatever order they came.
|
|
104
|
+
*/
|
|
105
|
+
export declare function rankPrivacyClasses(names: Iterable<string>): string[];
|
|
106
|
+
/**
|
|
107
|
+
* The strongest of `names`, the class a value is masked with when it carries several and is masked whole. See
|
|
108
|
+
* {@link rankPrivacyClasses}. `undefined` for none.
|
|
109
|
+
*/
|
|
110
|
+
export declare function strongestPrivacyClass(names: Iterable<string>): string | undefined;
|
|
111
|
+
/**
|
|
112
|
+
* The classes a schema's own `privacy` meta records: one class as its name, several as a list, strongest first. Read
|
|
113
|
+
* from this exact schema, never through a wrapper. Empty where it records none.
|
|
114
|
+
*/
|
|
115
|
+
export declare function ownPrivacyClasses(schema: z.ZodType): string[];
|
|
116
|
+
/** What {@link definePrivacyClass} takes. */
|
|
117
|
+
export interface PrivacyClassSpec<C extends string> {
|
|
118
|
+
/** The class name: a lowercase identifier, unique across the isolate. */
|
|
119
|
+
name: C;
|
|
120
|
+
/** What the class means. Defaults to a sentence naming it as adopter-registered. */
|
|
121
|
+
description?: string;
|
|
122
|
+
/** How a value masks. Defaults to the `[name]` placeholder. */
|
|
123
|
+
mask?: PrivacyMask;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Register a class of the adopter's own — `genetic`, `biometric`, whatever their regulator names — and get its
|
|
127
|
+
* marker back. Usable exactly like the built-ins: the same `meta`, the same brand, the same gate, the same
|
|
128
|
+
* inventory row.
|
|
129
|
+
*
|
|
130
|
+
* **A duplicate is refused at registration**, a built-in name included. Two modules each believing they own
|
|
131
|
+
* `genetic` would disagree about its mask, and the one that loaded second would win silently.
|
|
132
|
+
*/
|
|
133
|
+
export declare function definePrivacyClass<const C extends string>(spec: PrivacyClassSpec<C>): PrivacyMarker<C>;
|
|
134
|
+
/** Mark a field as a credential or bearer artifact. See {@link BUILT_INS}. */
|
|
135
|
+
export declare const secret: PrivacyMarker<"secret">;
|
|
136
|
+
/** Mark a field as personal data under GDPR or CCPA. */
|
|
137
|
+
export declare const pii: PrivacyMarker<"pii">;
|
|
138
|
+
/** Mark a field as Protected Health Information under HIPAA. */
|
|
139
|
+
export declare const phi: PrivacyMarker<"phi">;
|
|
140
|
+
/** Mark a field as cardholder data under PCI-DSS. Masks to first six and last four. */
|
|
141
|
+
export declare const pci: PrivacyMarker<"pci">;
|
|
142
|
+
//# sourceMappingURL=classes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classes.d.ts","sourceRoot":"","sources":["../../src/privacy/classes.ts"],"names":[],"mappings":"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"}
|