@nebutra/contracts 2.0.0 → 3.0.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/.turbo/turbo-build.log +12 -12
- package/.turbo/turbo-test.log +5 -5
- package/.turbo/turbo-typecheck.log +1 -1
- package/CHANGELOG.md +2 -0
- package/dist/admin.d.ts +18 -1
- package/dist/admin.js +5 -1
- package/dist/{chunk-F4BR76CX.js → chunk-BX2ZIODN.js} +3 -3
- package/dist/chunk-BX2ZIODN.js.map +1 -0
- package/dist/{chunk-ERZTZ3PW.js → chunk-G65TWQGE.js} +18 -2
- package/dist/{chunk-ERZTZ3PW.js.map → chunk-G65TWQGE.js.map} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +6 -2
- package/dist/notifications.d.ts +0 -3
- package/dist/notifications.js +1 -1
- package/package.json +1 -1
- package/src/admin.ts +31 -0
- package/src/notifications.ts +2 -2
- package/dist/chunk-F4BR76CX.js.map +0 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @nebutra/contracts@
|
|
2
|
+
> @nebutra/contracts@3.0.0 build /home/runner/work/Nebutra-Sailor/Nebutra-Sailor/packages/commerce/contracts
|
|
3
3
|
> tsup
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/admin.ts, src/billing.ts, src/events.ts, src/identity.ts, src/index.ts, src/notifications.ts, src/sleptons.ts
|
|
@@ -9,39 +9,39 @@
|
|
|
9
9
|
[34mCLI[39m Target: es2022
|
|
10
10
|
[34mCLI[39m Cleaning output folder
|
|
11
11
|
[34mESM[39m Build start
|
|
12
|
-
[32mESM[39m [1mdist/admin.js [22m[32m1.
|
|
12
|
+
[32mESM[39m [1mdist/admin.js [22m[32m1.12 KB[39m
|
|
13
13
|
[32mESM[39m [1mdist/billing.js [22m[32m332.00 B[39m
|
|
14
14
|
[32mESM[39m [1mdist/events.js [22m[32m173.00 B[39m
|
|
15
15
|
[32mESM[39m [1mdist/identity.js [22m[32m563.00 B[39m
|
|
16
|
-
[32mESM[39m [1mdist/index.js [22m[32m4.
|
|
17
|
-
[32mESM[39m [1mdist/chunk-
|
|
16
|
+
[32mESM[39m [1mdist/index.js [22m[32m4.44 KB[39m
|
|
17
|
+
[32mESM[39m [1mdist/chunk-G65TWQGE.js [22m[32m8.52 KB[39m
|
|
18
18
|
[32mESM[39m [1mdist/chunk-NFJTVIKD.js [22m[32m1.32 KB[39m
|
|
19
19
|
[32mESM[39m [1mdist/chunk-2NXI4PJM.js [22m[32m565.00 B[39m
|
|
20
20
|
[32mESM[39m [1mdist/chunk-5JNQ2KAT.js [22m[32m2.07 KB[39m
|
|
21
21
|
[32mESM[39m [1mdist/notifications.js [22m[32m1.11 KB[39m
|
|
22
|
-
[32mESM[39m [1mdist/chunk-F4BR76CX.js [22m[32m2.91 KB[39m
|
|
23
22
|
[32mESM[39m [1mdist/sleptons.js [22m[32m1.40 KB[39m
|
|
23
|
+
[32mESM[39m [1mdist/chunk-BX2ZIODN.js [22m[32m2.88 KB[39m
|
|
24
24
|
[32mESM[39m [1mdist/chunk-PU65L2HQ.js [22m[32m6.74 KB[39m
|
|
25
25
|
[32mESM[39m [1mdist/admin.js.map [22m[32m71.00 B[39m
|
|
26
26
|
[32mESM[39m [1mdist/billing.js.map [22m[32m71.00 B[39m
|
|
27
27
|
[32mESM[39m [1mdist/events.js.map [22m[32m71.00 B[39m
|
|
28
28
|
[32mESM[39m [1mdist/identity.js.map [22m[32m71.00 B[39m
|
|
29
29
|
[32mESM[39m [1mdist/index.js.map [22m[32m71.00 B[39m
|
|
30
|
-
[32mESM[39m [1mdist/chunk-
|
|
30
|
+
[32mESM[39m [1mdist/chunk-G65TWQGE.js.map [22m[32m18.03 KB[39m
|
|
31
31
|
[32mESM[39m [1mdist/chunk-NFJTVIKD.js.map [22m[32m2.78 KB[39m
|
|
32
32
|
[32mESM[39m [1mdist/chunk-2NXI4PJM.js.map [22m[32m1.16 KB[39m
|
|
33
33
|
[32mESM[39m [1mdist/chunk-5JNQ2KAT.js.map [22m[32m4.47 KB[39m
|
|
34
34
|
[32mESM[39m [1mdist/notifications.js.map [22m[32m71.00 B[39m
|
|
35
|
-
[32mESM[39m [1mdist/chunk-F4BR76CX.js.map [22m[32m6.05 KB[39m
|
|
36
35
|
[32mESM[39m [1mdist/sleptons.js.map [22m[32m71.00 B[39m
|
|
36
|
+
[32mESM[39m [1mdist/chunk-BX2ZIODN.js.map [22m[32m6.00 KB[39m
|
|
37
37
|
[32mESM[39m [1mdist/chunk-PU65L2HQ.js.map [22m[32m14.02 KB[39m
|
|
38
|
-
[32mESM[39m ⚡️ Build success in
|
|
38
|
+
[32mESM[39m ⚡️ Build success in 96ms
|
|
39
39
|
[34mDTS[39m Build start
|
|
40
|
-
[32mDTS[39m ⚡️ Build success in
|
|
41
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[32m3.
|
|
42
|
-
[32mDTS[39m [1mdist/admin.d.ts [22m[
|
|
40
|
+
[32mDTS[39m ⚡️ Build success in 28456ms
|
|
41
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m3.18 KB[39m
|
|
42
|
+
[32mDTS[39m [1mdist/admin.d.ts [22m[32m15.67 KB[39m
|
|
43
43
|
[32mDTS[39m [1mdist/billing.d.ts [22m[32m2.11 KB[39m
|
|
44
44
|
[32mDTS[39m [1mdist/events.d.ts [22m[32m1020.00 B[39m
|
|
45
45
|
[32mDTS[39m [1mdist/identity.d.ts [22m[32m4.03 KB[39m
|
|
46
|
-
[32mDTS[39m [1mdist/notifications.d.ts [22m[32m6.
|
|
46
|
+
[32mDTS[39m [1mdist/notifications.d.ts [22m[32m6.02 KB[39m
|
|
47
47
|
[32mDTS[39m [1mdist/sleptons.d.ts [22m[32m21.11 KB[39m
|
package/.turbo/turbo-test.log
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
|
|
2
|
-
> @nebutra/contracts@
|
|
2
|
+
> @nebutra/contracts@3.0.0 test /home/runner/work/Nebutra-Sailor/Nebutra-Sailor/packages/commerce/contracts
|
|
3
3
|
> vitest run
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
[1m[30m[46m RUN [49m[39m[22m [36mv4.1.4 [39m[90m/home/runner/work/Nebutra-Sailor/Nebutra-Sailor/packages/commerce/contracts[39m
|
|
7
7
|
|
|
8
|
-
[32m✓[39m src/__tests__/admin.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m
|
|
9
|
-
[32m✓[39m src/sleptons.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m
|
|
8
|
+
[32m✓[39m src/__tests__/admin.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m 110[2mms[22m[39m
|
|
9
|
+
[32m✓[39m src/sleptons.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m 136[2mms[22m[39m
|
|
10
10
|
|
|
11
11
|
[2m Test Files [22m [1m[32m2 passed[39m[22m[90m (2)[39m
|
|
12
12
|
[2m Tests [22m [1m[32m11 passed[39m[22m[90m (11)[39m
|
|
13
|
-
[2m Start at [22m
|
|
14
|
-
[2m Duration [22m 1.
|
|
13
|
+
[2m Start at [22m 08:50:36
|
|
14
|
+
[2m Duration [22m 1.77s[2m (transform 700ms, setup 0ms, import 1.66s, tests 246ms, environment 0ms)[22m
|
|
15
15
|
|
package/CHANGELOG.md
CHANGED
package/dist/admin.d.ts
CHANGED
|
@@ -412,5 +412,22 @@ type AdminError = z.infer<typeof AdminErrorSchema>;
|
|
|
412
412
|
declare function assertApplyAllowed(action: AdminAction, request: ActionRequest): AdminError | null;
|
|
413
413
|
/** Resolve a contract path against the manifest origin. */
|
|
414
414
|
declare function resolveContractUrl(manifest: Pick<AdminManifest, "origin">, path: string): string;
|
|
415
|
+
/**
|
|
416
|
+
* The HTTP status an admin error travels as.
|
|
417
|
+
*
|
|
418
|
+
* Cloudflare sits in front of every admin and product host, and it replaces an
|
|
419
|
+
* origin's `502` or `504` with its own branded HTML error page. The body we
|
|
420
|
+
* wrote — the code and the message the operator needs — is discarded before the
|
|
421
|
+
* browser sees it, so the console can only report `network · HTTP 502`. A
|
|
422
|
+
* contract endpoint therefore never answers with a gateway status: an upstream
|
|
423
|
+
* that failed is `503`, and a fault of our own is `500`. Both reach the client
|
|
424
|
+
* with their JSON envelope intact.
|
|
425
|
+
*/
|
|
426
|
+
declare const ADMIN_ERROR_STATUS: Record<AdminError["error"]["code"], number>;
|
|
427
|
+
/**
|
|
428
|
+
* Narrow an arbitrary status to one that survives the CDN, preserving anything
|
|
429
|
+
* already safe. Use it when echoing an upstream contract call's status.
|
|
430
|
+
*/
|
|
431
|
+
declare function cdnSafeStatus(status: number | undefined, fallback?: number): number;
|
|
415
432
|
|
|
416
|
-
export { ADMIN_CONTRACT_VERSION, type ActionPlan, ActionPlanSchema, type ActionRequest, ActionRequestSchema, type ActionResult, ActionResultSchema, type AdminAction, AdminActionSchema, type AdminColumn, AdminColumnSchema, type AdminDomain, type AdminDomainId, AdminDomainIdSchema, AdminDomainSchema, type AdminError, AdminErrorSchema, type AdminManifest, AdminManifestSchema, type AdminPolicy, AdminPolicySchema, type AdminResource, AdminResourceSchema, type AdminSeverity, AdminSeveritySchema, type AdminSignal, AdminSignalSchema, type AdminStatus, AdminStatusSchema, PlanDiffEntrySchema, type ResourceList, ResourceListSchema, STAFF_ROLE_RANK, type SignalReading, SignalReadingSchema, type StaffRole, StaffRoleSchema, assertApplyAllowed, resolveContractUrl, roleAtLeast };
|
|
433
|
+
export { ADMIN_CONTRACT_VERSION, ADMIN_ERROR_STATUS, type ActionPlan, ActionPlanSchema, type ActionRequest, ActionRequestSchema, type ActionResult, ActionResultSchema, type AdminAction, AdminActionSchema, type AdminColumn, AdminColumnSchema, type AdminDomain, type AdminDomainId, AdminDomainIdSchema, AdminDomainSchema, type AdminError, AdminErrorSchema, type AdminManifest, AdminManifestSchema, type AdminPolicy, AdminPolicySchema, type AdminResource, AdminResourceSchema, type AdminSeverity, AdminSeveritySchema, type AdminSignal, AdminSignalSchema, type AdminStatus, AdminStatusSchema, PlanDiffEntrySchema, type ResourceList, ResourceListSchema, STAFF_ROLE_RANK, type SignalReading, SignalReadingSchema, type StaffRole, StaffRoleSchema, assertApplyAllowed, cdnSafeStatus, resolveContractUrl, roleAtLeast };
|
package/dist/admin.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ADMIN_CONTRACT_VERSION,
|
|
3
|
+
ADMIN_ERROR_STATUS,
|
|
3
4
|
ActionPlanSchema,
|
|
4
5
|
ActionRequestSchema,
|
|
5
6
|
ActionResultSchema,
|
|
@@ -20,11 +21,13 @@ import {
|
|
|
20
21
|
SignalReadingSchema,
|
|
21
22
|
StaffRoleSchema,
|
|
22
23
|
assertApplyAllowed,
|
|
24
|
+
cdnSafeStatus,
|
|
23
25
|
resolveContractUrl,
|
|
24
26
|
roleAtLeast
|
|
25
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-G65TWQGE.js";
|
|
26
28
|
export {
|
|
27
29
|
ADMIN_CONTRACT_VERSION,
|
|
30
|
+
ADMIN_ERROR_STATUS,
|
|
28
31
|
ActionPlanSchema,
|
|
29
32
|
ActionRequestSchema,
|
|
30
33
|
ActionResultSchema,
|
|
@@ -45,6 +48,7 @@ export {
|
|
|
45
48
|
SignalReadingSchema,
|
|
46
49
|
StaffRoleSchema,
|
|
47
50
|
assertApplyAllowed,
|
|
51
|
+
cdnSafeStatus,
|
|
48
52
|
resolveContractUrl,
|
|
49
53
|
roleAtLeast
|
|
50
54
|
};
|
|
@@ -8,9 +8,9 @@ var NotificationFrequencyContractSchema = z.enum([
|
|
|
8
8
|
"never"
|
|
9
9
|
]);
|
|
10
10
|
var NotificationRuntimeStatusContractSchema = z.object({
|
|
11
|
-
provider: z.enum(["
|
|
11
|
+
provider: z.enum(["direct"]),
|
|
12
12
|
providerLabel: z.string().min(1),
|
|
13
|
-
mode: z.enum(["
|
|
13
|
+
mode: z.enum(["self_hosted", "preview"]),
|
|
14
14
|
canManagePreferences: z.boolean(),
|
|
15
15
|
canViewInbox: z.boolean(),
|
|
16
16
|
canMarkInboxRead: z.boolean(),
|
|
@@ -82,4 +82,4 @@ export {
|
|
|
82
82
|
NotificationSettingsUpdateRequestContractSchema,
|
|
83
83
|
NotificationSettingsUpdateResponseContractSchema
|
|
84
84
|
};
|
|
85
|
-
//# sourceMappingURL=chunk-
|
|
85
|
+
//# sourceMappingURL=chunk-BX2ZIODN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/notifications.ts"],"sourcesContent":["import { z } from \"zod\";\n\nexport const NotificationChannelContractSchema = z.enum([\"in_app\", \"email\", \"push\", \"sms\", \"chat\"]);\nexport type NotificationChannelContract = z.infer<typeof NotificationChannelContractSchema>;\n\nexport const NotificationFrequencyContractSchema = z.enum([\n \"immediate\",\n \"daily\",\n \"weekly\",\n \"never\",\n]);\nexport type NotificationFrequencyContract = z.infer<typeof NotificationFrequencyContractSchema>;\n\nexport const NotificationRuntimeStatusContractSchema = z.object({\n provider: z.enum([\"direct\"]),\n providerLabel: z.string().min(1),\n mode: z.enum([\"self_hosted\", \"preview\"]),\n canManagePreferences: z.boolean(),\n canViewInbox: z.boolean(),\n canMarkInboxRead: z.boolean(),\n summary: z.string().min(1),\n reason: z.string().optional(),\n missing: z.array(z.string()),\n});\nexport type NotificationRuntimeStatusContract = z.infer<\n typeof NotificationRuntimeStatusContractSchema\n>;\n\nexport const NotificationPreferenceContractSchema = z.object({\n userId: z.string().min(1),\n tenantId: z.string().min(1).optional(),\n channel: NotificationChannelContractSchema,\n enabled: z.boolean(),\n disabledCategories: z.array(z.string()).optional(),\n frequency: NotificationFrequencyContractSchema,\n updatedAt: z.string().datetime().optional(),\n});\nexport type NotificationPreferenceContract = z.infer<typeof NotificationPreferenceContractSchema>;\n\nexport const NotificationItemContractSchema = z.object({\n id: z.string().min(1),\n userId: z.string().min(1),\n tenantId: z.string().min(1).optional(),\n type: z.string().min(1),\n title: z.string(),\n body: z.string(),\n data: z.record(z.string(), z.unknown()).optional(),\n read: z.boolean(),\n createdAt: z.string().datetime(),\n updatedAt: z.string().datetime(),\n});\nexport type NotificationItemContract = z.infer<typeof NotificationItemContractSchema>;\n\nexport const NotificationListQueryContractSchema = z.object({\n limit: z.coerce.number().int().min(1).max(100).default(50),\n offset: z.coerce.number().int().min(0).default(0),\n unreadOnly: z.coerce.boolean().optional(),\n});\nexport type NotificationListQueryContract = z.infer<typeof NotificationListQueryContractSchema>;\n\nexport const NotificationListResponseContractSchema = z.object({\n items: z.array(NotificationItemContractSchema),\n total: z.number().int().nonnegative(),\n unreadCount: z.number().int().nonnegative(),\n});\nexport type NotificationListResponseContract = z.infer<\n typeof NotificationListResponseContractSchema\n>;\n\nexport const NotificationUnreadCountResponseContractSchema = z.object({\n count: z.number().int().nonnegative(),\n});\nexport type NotificationUnreadCountResponseContract = z.infer<\n typeof NotificationUnreadCountResponseContractSchema\n>;\n\nexport const NotificationMarkReadRequestContractSchema = z.object({\n ids: z.array(z.string().min(1)).min(1).max(100),\n});\nexport type NotificationMarkReadRequestContract = z.infer<\n typeof NotificationMarkReadRequestContractSchema\n>;\n\nexport const NotificationMutationCountResponseContractSchema = z.object({\n count: z.number().int().nonnegative(),\n});\nexport type NotificationMutationCountResponseContract = z.infer<\n typeof NotificationMutationCountResponseContractSchema\n>;\n\nexport const NotificationSettingsUpdateRequestContractSchema = z.object({\n type: z.string().min(1),\n channel: NotificationChannelContractSchema,\n enabled: z.boolean(),\n});\nexport type NotificationSettingsUpdateRequestContract = z.infer<\n typeof NotificationSettingsUpdateRequestContractSchema\n>;\n\nexport const NotificationSettingsUpdateResponseContractSchema = z.object({\n ok: z.literal(true),\n preference: NotificationPreferenceContractSchema,\n});\nexport type NotificationSettingsUpdateResponseContract = z.infer<\n typeof NotificationSettingsUpdateResponseContractSchema\n>;\n"],"mappings":"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","names":[]}
|
|
@@ -228,6 +228,20 @@ function assertApplyAllowed(action, request) {
|
|
|
228
228
|
function resolveContractUrl(manifest, path) {
|
|
229
229
|
return new URL(path, manifest.origin).toString();
|
|
230
230
|
}
|
|
231
|
+
var ADMIN_ERROR_STATUS = {
|
|
232
|
+
unauthenticated: 401,
|
|
233
|
+
forbidden: 403,
|
|
234
|
+
not_found: 404,
|
|
235
|
+
invalid_input: 400,
|
|
236
|
+
plan_required: 409,
|
|
237
|
+
plan_expired: 409,
|
|
238
|
+
upstream_unavailable: 503,
|
|
239
|
+
internal: 500
|
|
240
|
+
};
|
|
241
|
+
function cdnSafeStatus(status, fallback = 503) {
|
|
242
|
+
if (!status || status === 502 || status === 504 || status < 400 || status > 599) return fallback;
|
|
243
|
+
return status;
|
|
244
|
+
}
|
|
231
245
|
|
|
232
246
|
export {
|
|
233
247
|
ADMIN_CONTRACT_VERSION,
|
|
@@ -252,6 +266,8 @@ export {
|
|
|
252
266
|
SignalReadingSchema,
|
|
253
267
|
AdminErrorSchema,
|
|
254
268
|
assertApplyAllowed,
|
|
255
|
-
resolveContractUrl
|
|
269
|
+
resolveContractUrl,
|
|
270
|
+
ADMIN_ERROR_STATUS,
|
|
271
|
+
cdnSafeStatus
|
|
256
272
|
};
|
|
257
|
-
//# sourceMappingURL=chunk-
|
|
273
|
+
//# sourceMappingURL=chunk-G65TWQGE.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/admin.ts"],"sourcesContent":["import { z } from \"zod\";\n\n/**\n * Admin Contract — `nebutra.admin/v1`.\n *\n * Every Nebutra SaaS exposes one manifest describing the admin surface it\n * owns: resources (nouns), actions (audited verbs, plan → apply), signals\n * (probed facts) and policies (actions the system runs by itself). The\n * platform admin renders any product from its manifest; an agent derives\n * tools from it. Nothing product-specific lives in the renderer.\n *\n * See docs/plans/2026-09-08-admin-of-admins-model.md.\n */\n\nexport const ADMIN_CONTRACT_VERSION = \"nebutra.admin/v1\" as const;\n\n/** One status vocabulary. `unknown` is first-class and never renders green. */\nexport const AdminStatusSchema = z.enum([\"healthy\", \"degraded\", \"down\", \"unknown\"]);\nexport type AdminStatus = z.infer<typeof AdminStatusSchema>;\n\n/** One role ladder; product roles map onto it, staff grants mean the same everywhere. */\nexport const StaffRoleSchema = z.enum([\n \"platform_readonly\",\n \"platform_support\",\n \"platform_operator\",\n \"platform_owner\",\n]);\nexport type StaffRole = z.infer<typeof StaffRoleSchema>;\nexport const STAFF_ROLE_RANK: Record<StaffRole, number> = {\n platform_readonly: 0,\n platform_support: 1,\n platform_operator: 2,\n platform_owner: 3,\n};\nexport function roleAtLeast(role: StaffRole, required: StaffRole): boolean {\n return STAFF_ROLE_RANK[role] >= STAFF_ROLE_RANK[required];\n}\n\nexport const AdminSeveritySchema = z.enum([\"info\", \"warn\", \"critical\"]);\nexport type AdminSeverity = z.infer<typeof AdminSeveritySchema>;\n\n/** The canonical eleven. A product declares the subset it has. */\nexport const AdminDomainIdSchema = z.enum([\n \"identity\",\n \"access\",\n \"commerce\",\n \"usage\",\n \"catalog\",\n \"operations\",\n \"integrations\",\n \"trust\",\n \"support\",\n \"growth\",\n \"settings\",\n // Platform-only cross-cutting domain: shared AI supply (router).\n \"supply\",\n]);\nexport type AdminDomainId = z.infer<typeof AdminDomainIdSchema>;\n\nconst IdSchema = z\n .string()\n .min(1)\n .max(64)\n .regex(/^[a-z][a-z0-9._-]*$/, \"ids are lowercase dotted identifiers\");\nconst UrlPathSchema = z.string().min(1).regex(/^\\//, \"contract urls are origin-relative paths\");\n\nexport const AdminColumnSchema = z.object({\n key: z.string().min(1),\n label: z.string().min(1),\n kind: z.enum([\"text\", \"mono\", \"status\", \"badge\", \"number\", \"time\", \"link\"]).default(\"text\"),\n /** Right-align numbers; the renderer does not guess from values. */\n align: z.enum([\"start\", \"end\"]).default(\"start\"),\n});\nexport type AdminColumn = z.infer<typeof AdminColumnSchema>;\n\nexport const AdminResourceSchema = z.object({\n id: IdSchema,\n label: z.string().min(1),\n /** `GET list` → ResourceList */\n list: UrlPathSchema,\n /** `GET detail` with `{id}` placeholder → one item */\n detail: UrlPathSchema.optional(),\n columns: z.array(AdminColumnSchema).min(1),\n /** Column key that identifies a row. */\n key: z.string().min(1).default(\"id\"),\n search: z.boolean().default(false),\n /** Action ids applicable per row. */\n actions: z.array(IdSchema).default([]),\n});\nexport type AdminResource = z.infer<typeof AdminResourceSchema>;\n\nexport const AdminActionSchema = z.object({\n id: IdSchema,\n verb: z.string().min(1),\n /** Resource the action belongs to; omitted = domain-level action. */\n resource: IdSchema.optional(),\n /** Minimum staff role. Read-only tier never sees write controls. */\n role: StaffRoleSchema,\n /** `POST url` with ActionRequest (`mode: plan | apply`). */\n url: UrlPathSchema,\n /** Plan step is mandatory; `false` only for idempotent, non-destructive refreshes. */\n plan: z.boolean().default(true),\n destructive: z.boolean().default(false),\n /** JSON Schema for `input`; doubles as the MCP tool inputSchema. */\n input: z.record(z.string(), z.unknown()).optional(),\n description: z.string().optional(),\n});\nexport type AdminAction = z.infer<typeof AdminActionSchema>;\n\nexport const AdminSignalSchema = z.object({\n id: IdSchema,\n label: z.string().min(1),\n severity: AdminSeveritySchema,\n /** `GET probe` → SignalReading. Probed, never configured. */\n probe: UrlPathSchema,\n resource: IdSchema.optional(),\n /** Action that resolves the signal when raised. */\n action: IdSchema.optional(),\n});\nexport type AdminSignal = z.infer<typeof AdminSignalSchema>;\n\nexport const AdminPolicySchema = z.object({\n id: IdSchema,\n label: z.string().min(1),\n /** Event name (`nebutra/<domain>.<thing>.<verb>`) that triggers the policy. */\n on: z.string().min(1),\n runs: IdSchema,\n enabled: z.boolean().default(true),\n /** Natural-language intent the policy was compiled from, when it was. */\n intent: z.string().optional(),\n});\nexport type AdminPolicy = z.infer<typeof AdminPolicySchema>;\n\nexport const AdminDomainSchema = z.object({\n id: AdminDomainIdSchema,\n label: z.string().min(1),\n resources: z.array(AdminResourceSchema).default([]),\n actions: z.array(AdminActionSchema).default([]),\n signals: z.array(AdminSignalSchema).default([]),\n policies: z.array(AdminPolicySchema).default([]),\n /** Product-owned browser surface for what the generic renderer cannot express. */\n slot: UrlPathSchema.optional(),\n});\nexport type AdminDomain = z.infer<typeof AdminDomainSchema>;\n\nexport const AdminManifestSchema = z\n .object({\n contract: z.literal(ADMIN_CONTRACT_VERSION),\n product: IdSchema,\n label: z.string().min(1),\n version: z.string().min(1),\n /** Absolute origin every relative url resolves against. */\n origin: z.string().url(),\n graph: z.enum([\"core\", \"runtime\", \"labs\"]),\n status: z.enum([\"stable\", \"foundation\", \"wip\", \"experimental\"]),\n /** `GET health` → @nebutra/health HealthCheckResult. */\n health: UrlPathSchema,\n /** `GET audit?…` → audit events (nebutra.audit/v1). */\n audit: UrlPathSchema.optional(),\n domains: z.array(AdminDomainSchema).min(1),\n })\n .superRefine((m, ctx) => {\n for (const d of m.domains) {\n const actionIds = new Set(d.actions.map((a) => a.id));\n const resourceIds = new Set(d.resources.map((r) => r.id));\n for (const r of d.resources) {\n for (const a of r.actions) {\n if (!actionIds.has(a)) {\n ctx.addIssue({\n code: \"custom\",\n message: `resource ${r.id} references unknown action ${a}`,\n });\n }\n }\n }\n for (const s of d.signals) {\n if (s.action && !actionIds.has(s.action)) {\n ctx.addIssue({\n code: \"custom\",\n message: `signal ${s.id} references unknown action ${s.action}`,\n });\n }\n if (s.resource && !resourceIds.has(s.resource)) {\n ctx.addIssue({\n code: \"custom\",\n message: `signal ${s.id} references unknown resource ${s.resource}`,\n });\n }\n }\n for (const p of d.policies) {\n if (!actionIds.has(p.runs)) {\n ctx.addIssue({ code: \"custom\", message: `policy ${p.id} runs unknown action ${p.runs}` });\n }\n }\n }\n });\nexport type AdminManifest = z.infer<typeof AdminManifestSchema>;\n\n// -----------------------------------------------------------------------------\n// Wire envelopes\n// -----------------------------------------------------------------------------\n\nexport const ResourceListSchema = z.object({\n items: z.array(z.record(z.string(), z.unknown())),\n total: z.number().int().min(0),\n /** When the list was produced from live probes; omitted for pure reads. */\n probedAt: z.string().datetime().optional(),\n});\nexport type ResourceList = z.infer<typeof ResourceListSchema>;\n\nexport const ActionRequestSchema = z.discriminatedUnion(\"mode\", [\n z.object({ mode: z.literal(\"plan\"), input: z.record(z.string(), z.unknown()).default({}) }),\n z.object({\n mode: z.literal(\"apply\"),\n input: z.record(z.string(), z.unknown()).default({}),\n /** Required when the action is destructive; ties the apply to a reviewed plan. */\n planId: z.string().min(1).optional(),\n }),\n]);\nexport type ActionRequest = z.infer<typeof ActionRequestSchema>;\n\nexport const PlanDiffEntrySchema = z.object({\n op: z.enum([\"add\", \"remove\", \"change\"]),\n path: z.string().min(1),\n from: z.unknown().optional(),\n to: z.unknown().optional(),\n});\nexport const ActionPlanSchema = z.object({\n planId: z.string().min(1),\n summary: z.string().min(1),\n diff: z.array(PlanDiffEntrySchema),\n affected: z\n .array(z.object({ resource: IdSchema, id: z.string(), label: z.string().optional() }))\n .default([]),\n warnings: z.array(z.string()).default([]),\n /** Plans expire; an apply after this is refused. */\n expiresAt: z.string().datetime(),\n});\nexport type ActionPlan = z.infer<typeof ActionPlanSchema>;\n\nexport const ActionResultSchema = z.object({\n /** Audit event id written by the product for this apply. */\n auditId: z.string().min(1),\n summary: z.string().min(1),\n result: z.record(z.string(), z.unknown()).optional(),\n});\nexport type ActionResult = z.infer<typeof ActionResultSchema>;\n\nexport const SignalReadingSchema = z.object({\n id: IdSchema,\n status: z.enum([\"ok\", \"raised\", \"unknown\"]),\n severity: AdminSeveritySchema,\n probedAt: z.string().datetime(),\n title: z.string().optional(),\n detail: z.string().optional(),\n resource: IdSchema.optional(),\n action: IdSchema.optional(),\n data: z.record(z.string(), z.unknown()).optional(),\n});\nexport type SignalReading = z.infer<typeof SignalReadingSchema>;\n\n/** Standard error body for contract endpoints. */\nexport const AdminErrorSchema = z.object({\n error: z.object({\n code: z.enum([\n \"unauthenticated\",\n \"forbidden\",\n \"not_found\",\n \"invalid_input\",\n \"plan_required\",\n \"plan_expired\",\n \"upstream_unavailable\",\n \"internal\",\n ]),\n message: z.string(),\n }),\n});\nexport type AdminError = z.infer<typeof AdminErrorSchema>;\n\n/** Validate an apply against its action: destructive applies must reference a plan. */\nexport function assertApplyAllowed(action: AdminAction, request: ActionRequest): AdminError | null {\n if (request.mode !== \"apply\") return null;\n if ((action.destructive || action.plan) && !request.planId) {\n return {\n error: {\n code: \"plan_required\",\n message: `${action.id} requires a reviewed plan before apply`,\n },\n };\n }\n return null;\n}\n\n/** Resolve a contract path against the manifest origin. */\nexport function resolveContractUrl(manifest: Pick<AdminManifest, \"origin\">, path: string): string {\n return new URL(path, manifest.origin).toString();\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/admin.ts"],"sourcesContent":["import { z } from \"zod\";\n\n/**\n * Admin Contract — `nebutra.admin/v1`.\n *\n * Every Nebutra SaaS exposes one manifest describing the admin surface it\n * owns: resources (nouns), actions (audited verbs, plan → apply), signals\n * (probed facts) and policies (actions the system runs by itself). The\n * platform admin renders any product from its manifest; an agent derives\n * tools from it. Nothing product-specific lives in the renderer.\n *\n * See docs/plans/2026-09-08-admin-of-admins-model.md.\n */\n\nexport const ADMIN_CONTRACT_VERSION = \"nebutra.admin/v1\" as const;\n\n/** One status vocabulary. `unknown` is first-class and never renders green. */\nexport const AdminStatusSchema = z.enum([\"healthy\", \"degraded\", \"down\", \"unknown\"]);\nexport type AdminStatus = z.infer<typeof AdminStatusSchema>;\n\n/** One role ladder; product roles map onto it, staff grants mean the same everywhere. */\nexport const StaffRoleSchema = z.enum([\n \"platform_readonly\",\n \"platform_support\",\n \"platform_operator\",\n \"platform_owner\",\n]);\nexport type StaffRole = z.infer<typeof StaffRoleSchema>;\nexport const STAFF_ROLE_RANK: Record<StaffRole, number> = {\n platform_readonly: 0,\n platform_support: 1,\n platform_operator: 2,\n platform_owner: 3,\n};\nexport function roleAtLeast(role: StaffRole, required: StaffRole): boolean {\n return STAFF_ROLE_RANK[role] >= STAFF_ROLE_RANK[required];\n}\n\nexport const AdminSeveritySchema = z.enum([\"info\", \"warn\", \"critical\"]);\nexport type AdminSeverity = z.infer<typeof AdminSeveritySchema>;\n\n/** The canonical eleven. A product declares the subset it has. */\nexport const AdminDomainIdSchema = z.enum([\n \"identity\",\n \"access\",\n \"commerce\",\n \"usage\",\n \"catalog\",\n \"operations\",\n \"integrations\",\n \"trust\",\n \"support\",\n \"growth\",\n \"settings\",\n // Platform-only cross-cutting domain: shared AI supply (router).\n \"supply\",\n]);\nexport type AdminDomainId = z.infer<typeof AdminDomainIdSchema>;\n\nconst IdSchema = z\n .string()\n .min(1)\n .max(64)\n .regex(/^[a-z][a-z0-9._-]*$/, \"ids are lowercase dotted identifiers\");\nconst UrlPathSchema = z.string().min(1).regex(/^\\//, \"contract urls are origin-relative paths\");\n\nexport const AdminColumnSchema = z.object({\n key: z.string().min(1),\n label: z.string().min(1),\n kind: z.enum([\"text\", \"mono\", \"status\", \"badge\", \"number\", \"time\", \"link\"]).default(\"text\"),\n /** Right-align numbers; the renderer does not guess from values. */\n align: z.enum([\"start\", \"end\"]).default(\"start\"),\n});\nexport type AdminColumn = z.infer<typeof AdminColumnSchema>;\n\nexport const AdminResourceSchema = z.object({\n id: IdSchema,\n label: z.string().min(1),\n /** `GET list` → ResourceList */\n list: UrlPathSchema,\n /** `GET detail` with `{id}` placeholder → one item */\n detail: UrlPathSchema.optional(),\n columns: z.array(AdminColumnSchema).min(1),\n /** Column key that identifies a row. */\n key: z.string().min(1).default(\"id\"),\n search: z.boolean().default(false),\n /** Action ids applicable per row. */\n actions: z.array(IdSchema).default([]),\n});\nexport type AdminResource = z.infer<typeof AdminResourceSchema>;\n\nexport const AdminActionSchema = z.object({\n id: IdSchema,\n verb: z.string().min(1),\n /** Resource the action belongs to; omitted = domain-level action. */\n resource: IdSchema.optional(),\n /** Minimum staff role. Read-only tier never sees write controls. */\n role: StaffRoleSchema,\n /** `POST url` with ActionRequest (`mode: plan | apply`). */\n url: UrlPathSchema,\n /** Plan step is mandatory; `false` only for idempotent, non-destructive refreshes. */\n plan: z.boolean().default(true),\n destructive: z.boolean().default(false),\n /** JSON Schema for `input`; doubles as the MCP tool inputSchema. */\n input: z.record(z.string(), z.unknown()).optional(),\n description: z.string().optional(),\n});\nexport type AdminAction = z.infer<typeof AdminActionSchema>;\n\nexport const AdminSignalSchema = z.object({\n id: IdSchema,\n label: z.string().min(1),\n severity: AdminSeveritySchema,\n /** `GET probe` → SignalReading. Probed, never configured. */\n probe: UrlPathSchema,\n resource: IdSchema.optional(),\n /** Action that resolves the signal when raised. */\n action: IdSchema.optional(),\n});\nexport type AdminSignal = z.infer<typeof AdminSignalSchema>;\n\nexport const AdminPolicySchema = z.object({\n id: IdSchema,\n label: z.string().min(1),\n /** Event name (`nebutra/<domain>.<thing>.<verb>`) that triggers the policy. */\n on: z.string().min(1),\n runs: IdSchema,\n enabled: z.boolean().default(true),\n /** Natural-language intent the policy was compiled from, when it was. */\n intent: z.string().optional(),\n});\nexport type AdminPolicy = z.infer<typeof AdminPolicySchema>;\n\nexport const AdminDomainSchema = z.object({\n id: AdminDomainIdSchema,\n label: z.string().min(1),\n resources: z.array(AdminResourceSchema).default([]),\n actions: z.array(AdminActionSchema).default([]),\n signals: z.array(AdminSignalSchema).default([]),\n policies: z.array(AdminPolicySchema).default([]),\n /** Product-owned browser surface for what the generic renderer cannot express. */\n slot: UrlPathSchema.optional(),\n});\nexport type AdminDomain = z.infer<typeof AdminDomainSchema>;\n\nexport const AdminManifestSchema = z\n .object({\n contract: z.literal(ADMIN_CONTRACT_VERSION),\n product: IdSchema,\n label: z.string().min(1),\n version: z.string().min(1),\n /** Absolute origin every relative url resolves against. */\n origin: z.string().url(),\n graph: z.enum([\"core\", \"runtime\", \"labs\"]),\n status: z.enum([\"stable\", \"foundation\", \"wip\", \"experimental\"]),\n /** `GET health` → @nebutra/health HealthCheckResult. */\n health: UrlPathSchema,\n /** `GET audit?…` → audit events (nebutra.audit/v1). */\n audit: UrlPathSchema.optional(),\n domains: z.array(AdminDomainSchema).min(1),\n })\n .superRefine((m, ctx) => {\n for (const d of m.domains) {\n const actionIds = new Set(d.actions.map((a) => a.id));\n const resourceIds = new Set(d.resources.map((r) => r.id));\n for (const r of d.resources) {\n for (const a of r.actions) {\n if (!actionIds.has(a)) {\n ctx.addIssue({\n code: \"custom\",\n message: `resource ${r.id} references unknown action ${a}`,\n });\n }\n }\n }\n for (const s of d.signals) {\n if (s.action && !actionIds.has(s.action)) {\n ctx.addIssue({\n code: \"custom\",\n message: `signal ${s.id} references unknown action ${s.action}`,\n });\n }\n if (s.resource && !resourceIds.has(s.resource)) {\n ctx.addIssue({\n code: \"custom\",\n message: `signal ${s.id} references unknown resource ${s.resource}`,\n });\n }\n }\n for (const p of d.policies) {\n if (!actionIds.has(p.runs)) {\n ctx.addIssue({ code: \"custom\", message: `policy ${p.id} runs unknown action ${p.runs}` });\n }\n }\n }\n });\nexport type AdminManifest = z.infer<typeof AdminManifestSchema>;\n\n// -----------------------------------------------------------------------------\n// Wire envelopes\n// -----------------------------------------------------------------------------\n\nexport const ResourceListSchema = z.object({\n items: z.array(z.record(z.string(), z.unknown())),\n total: z.number().int().min(0),\n /** When the list was produced from live probes; omitted for pure reads. */\n probedAt: z.string().datetime().optional(),\n});\nexport type ResourceList = z.infer<typeof ResourceListSchema>;\n\nexport const ActionRequestSchema = z.discriminatedUnion(\"mode\", [\n z.object({ mode: z.literal(\"plan\"), input: z.record(z.string(), z.unknown()).default({}) }),\n z.object({\n mode: z.literal(\"apply\"),\n input: z.record(z.string(), z.unknown()).default({}),\n /** Required when the action is destructive; ties the apply to a reviewed plan. */\n planId: z.string().min(1).optional(),\n }),\n]);\nexport type ActionRequest = z.infer<typeof ActionRequestSchema>;\n\nexport const PlanDiffEntrySchema = z.object({\n op: z.enum([\"add\", \"remove\", \"change\"]),\n path: z.string().min(1),\n from: z.unknown().optional(),\n to: z.unknown().optional(),\n});\nexport const ActionPlanSchema = z.object({\n planId: z.string().min(1),\n summary: z.string().min(1),\n diff: z.array(PlanDiffEntrySchema),\n affected: z\n .array(z.object({ resource: IdSchema, id: z.string(), label: z.string().optional() }))\n .default([]),\n warnings: z.array(z.string()).default([]),\n /** Plans expire; an apply after this is refused. */\n expiresAt: z.string().datetime(),\n});\nexport type ActionPlan = z.infer<typeof ActionPlanSchema>;\n\nexport const ActionResultSchema = z.object({\n /** Audit event id written by the product for this apply. */\n auditId: z.string().min(1),\n summary: z.string().min(1),\n result: z.record(z.string(), z.unknown()).optional(),\n});\nexport type ActionResult = z.infer<typeof ActionResultSchema>;\n\nexport const SignalReadingSchema = z.object({\n id: IdSchema,\n status: z.enum([\"ok\", \"raised\", \"unknown\"]),\n severity: AdminSeveritySchema,\n probedAt: z.string().datetime(),\n title: z.string().optional(),\n detail: z.string().optional(),\n resource: IdSchema.optional(),\n action: IdSchema.optional(),\n data: z.record(z.string(), z.unknown()).optional(),\n});\nexport type SignalReading = z.infer<typeof SignalReadingSchema>;\n\n/** Standard error body for contract endpoints. */\nexport const AdminErrorSchema = z.object({\n error: z.object({\n code: z.enum([\n \"unauthenticated\",\n \"forbidden\",\n \"not_found\",\n \"invalid_input\",\n \"plan_required\",\n \"plan_expired\",\n \"upstream_unavailable\",\n \"internal\",\n ]),\n message: z.string(),\n }),\n});\nexport type AdminError = z.infer<typeof AdminErrorSchema>;\n\n/** Validate an apply against its action: destructive applies must reference a plan. */\nexport function assertApplyAllowed(action: AdminAction, request: ActionRequest): AdminError | null {\n if (request.mode !== \"apply\") return null;\n if ((action.destructive || action.plan) && !request.planId) {\n return {\n error: {\n code: \"plan_required\",\n message: `${action.id} requires a reviewed plan before apply`,\n },\n };\n }\n return null;\n}\n\n/** Resolve a contract path against the manifest origin. */\nexport function resolveContractUrl(manifest: Pick<AdminManifest, \"origin\">, path: string): string {\n return new URL(path, manifest.origin).toString();\n}\n\n/**\n * The HTTP status an admin error travels as.\n *\n * Cloudflare sits in front of every admin and product host, and it replaces an\n * origin's `502` or `504` with its own branded HTML error page. The body we\n * wrote — the code and the message the operator needs — is discarded before the\n * browser sees it, so the console can only report `network · HTTP 502`. A\n * contract endpoint therefore never answers with a gateway status: an upstream\n * that failed is `503`, and a fault of our own is `500`. Both reach the client\n * with their JSON envelope intact.\n */\nexport const ADMIN_ERROR_STATUS: Record<AdminError[\"error\"][\"code\"], number> = {\n unauthenticated: 401,\n forbidden: 403,\n not_found: 404,\n invalid_input: 400,\n plan_required: 409,\n plan_expired: 409,\n upstream_unavailable: 503,\n internal: 500,\n};\n\n/**\n * Narrow an arbitrary status to one that survives the CDN, preserving anything\n * already safe. Use it when echoing an upstream contract call's status.\n */\nexport function cdnSafeStatus(status: number | undefined, fallback = 503): number {\n if (!status || status === 502 || status === 504 || status < 400 || status > 599) return fallback;\n return status;\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { ADMIN_CONTRACT_VERSION, ActionPlan, ActionPlanSchema, ActionRequest, ActionRequestSchema, ActionResult, ActionResultSchema, AdminAction, AdminActionSchema, AdminColumn, AdminColumnSchema, AdminDomain, AdminDomainId, AdminDomainIdSchema, AdminDomainSchema, AdminError, AdminErrorSchema, AdminManifest, AdminManifestSchema, AdminPolicy, AdminPolicySchema, AdminResource, AdminResourceSchema, AdminSeverity, AdminSeveritySchema, AdminSignal, AdminSignalSchema, AdminStatus, AdminStatusSchema, PlanDiffEntrySchema, ResourceList, ResourceListSchema, STAFF_ROLE_RANK, SignalReading, SignalReadingSchema, StaffRole, StaffRoleSchema, assertApplyAllowed, resolveContractUrl, roleAtLeast } from './admin.js';
|
|
1
|
+
export { ADMIN_CONTRACT_VERSION, ADMIN_ERROR_STATUS, ActionPlan, ActionPlanSchema, ActionRequest, ActionRequestSchema, ActionResult, ActionResultSchema, AdminAction, AdminActionSchema, AdminColumn, AdminColumnSchema, AdminDomain, AdminDomainId, AdminDomainIdSchema, AdminDomainSchema, AdminError, AdminErrorSchema, AdminManifest, AdminManifestSchema, AdminPolicy, AdminPolicySchema, AdminResource, AdminResourceSchema, AdminSeverity, AdminSeveritySchema, AdminSignal, AdminSignalSchema, AdminStatus, AdminStatusSchema, PlanDiffEntrySchema, ResourceList, ResourceListSchema, STAFF_ROLE_RANK, SignalReading, SignalReadingSchema, StaffRole, StaffRoleSchema, assertApplyAllowed, cdnSafeStatus, resolveContractUrl, roleAtLeast } from './admin.js';
|
|
2
2
|
export { PricingCatalogVersion, PricingCatalogVersionSchema, UsageLedgerEntryInput, UsageLedgerEntryInputSchema, UsageLedgerSourceContract, UsageLedgerSourceContractSchema, UsageTypeContract, UsageTypeContractSchema } from './billing.js';
|
|
3
3
|
export { EventContext, EventContextSchema, EventEnvelope, EventEnvelopeSchema } from './events.js';
|
|
4
4
|
export { AuthProvider, AuthProviderSchema, CanonicalIdentity, CanonicalIdentitySchema, CanonicalPlan, CanonicalPlanSchema, CanonicalRole, CanonicalRoleSchema, ExternalAccountLink, ExternalAccountLinkSchema, NebutraOAuthScope, NebutraOAuthScopeSchema, OAuthClientRegistration, OAuthClientRegistrationSchema, OAuthClientType, OAuthClientTypeSchema, TenantHeaderContract, TenantHeaderContractSchema } from './identity.js';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ADMIN_CONTRACT_VERSION,
|
|
3
|
+
ADMIN_ERROR_STATUS,
|
|
3
4
|
ActionPlanSchema,
|
|
4
5
|
ActionRequestSchema,
|
|
5
6
|
ActionResultSchema,
|
|
@@ -20,9 +21,10 @@ import {
|
|
|
20
21
|
SignalReadingSchema,
|
|
21
22
|
StaffRoleSchema,
|
|
22
23
|
assertApplyAllowed,
|
|
24
|
+
cdnSafeStatus,
|
|
23
25
|
resolveContractUrl,
|
|
24
26
|
roleAtLeast
|
|
25
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-G65TWQGE.js";
|
|
26
28
|
import {
|
|
27
29
|
PricingCatalogVersionSchema,
|
|
28
30
|
UsageLedgerEntryInputSchema,
|
|
@@ -57,7 +59,7 @@ import {
|
|
|
57
59
|
NotificationSettingsUpdateRequestContractSchema,
|
|
58
60
|
NotificationSettingsUpdateResponseContractSchema,
|
|
59
61
|
NotificationUnreadCountResponseContractSchema
|
|
60
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-BX2ZIODN.js";
|
|
61
63
|
import {
|
|
62
64
|
DEFAULT_RESUME_MARGINS,
|
|
63
65
|
ExperienceKindSchema,
|
|
@@ -90,6 +92,7 @@ import {
|
|
|
90
92
|
} from "./chunk-PU65L2HQ.js";
|
|
91
93
|
export {
|
|
92
94
|
ADMIN_CONTRACT_VERSION,
|
|
95
|
+
ADMIN_ERROR_STATUS,
|
|
93
96
|
ActionPlanSchema,
|
|
94
97
|
ActionRequestSchema,
|
|
95
98
|
ActionResultSchema,
|
|
@@ -165,6 +168,7 @@ export {
|
|
|
165
168
|
UsageTypeContractSchema,
|
|
166
169
|
VentureStageSchema,
|
|
167
170
|
assertApplyAllowed,
|
|
171
|
+
cdnSafeStatus,
|
|
168
172
|
resolveContractUrl,
|
|
169
173
|
roleAtLeast
|
|
170
174
|
};
|
package/dist/notifications.d.ts
CHANGED
|
@@ -17,13 +17,10 @@ declare const NotificationFrequencyContractSchema: z.ZodEnum<{
|
|
|
17
17
|
type NotificationFrequencyContract = z.infer<typeof NotificationFrequencyContractSchema>;
|
|
18
18
|
declare const NotificationRuntimeStatusContractSchema: z.ZodObject<{
|
|
19
19
|
provider: z.ZodEnum<{
|
|
20
|
-
novu: "novu";
|
|
21
20
|
direct: "direct";
|
|
22
21
|
}>;
|
|
23
22
|
providerLabel: z.ZodString;
|
|
24
23
|
mode: z.ZodEnum<{
|
|
25
|
-
degraded: "degraded";
|
|
26
|
-
managed: "managed";
|
|
27
24
|
self_hosted: "self_hosted";
|
|
28
25
|
preview: "preview";
|
|
29
26
|
}>;
|
package/dist/notifications.js
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
NotificationSettingsUpdateRequestContractSchema,
|
|
12
12
|
NotificationSettingsUpdateResponseContractSchema,
|
|
13
13
|
NotificationUnreadCountResponseContractSchema
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-BX2ZIODN.js";
|
|
15
15
|
export {
|
|
16
16
|
NotificationChannelContractSchema,
|
|
17
17
|
NotificationFrequencyContractSchema,
|
package/package.json
CHANGED
package/src/admin.ts
CHANGED
|
@@ -295,3 +295,34 @@ export function assertApplyAllowed(action: AdminAction, request: ActionRequest):
|
|
|
295
295
|
export function resolveContractUrl(manifest: Pick<AdminManifest, "origin">, path: string): string {
|
|
296
296
|
return new URL(path, manifest.origin).toString();
|
|
297
297
|
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* The HTTP status an admin error travels as.
|
|
301
|
+
*
|
|
302
|
+
* Cloudflare sits in front of every admin and product host, and it replaces an
|
|
303
|
+
* origin's `502` or `504` with its own branded HTML error page. The body we
|
|
304
|
+
* wrote — the code and the message the operator needs — is discarded before the
|
|
305
|
+
* browser sees it, so the console can only report `network · HTTP 502`. A
|
|
306
|
+
* contract endpoint therefore never answers with a gateway status: an upstream
|
|
307
|
+
* that failed is `503`, and a fault of our own is `500`. Both reach the client
|
|
308
|
+
* with their JSON envelope intact.
|
|
309
|
+
*/
|
|
310
|
+
export const ADMIN_ERROR_STATUS: Record<AdminError["error"]["code"], number> = {
|
|
311
|
+
unauthenticated: 401,
|
|
312
|
+
forbidden: 403,
|
|
313
|
+
not_found: 404,
|
|
314
|
+
invalid_input: 400,
|
|
315
|
+
plan_required: 409,
|
|
316
|
+
plan_expired: 409,
|
|
317
|
+
upstream_unavailable: 503,
|
|
318
|
+
internal: 500,
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Narrow an arbitrary status to one that survives the CDN, preserving anything
|
|
323
|
+
* already safe. Use it when echoing an upstream contract call's status.
|
|
324
|
+
*/
|
|
325
|
+
export function cdnSafeStatus(status: number | undefined, fallback = 503): number {
|
|
326
|
+
if (!status || status === 502 || status === 504 || status < 400 || status > 599) return fallback;
|
|
327
|
+
return status;
|
|
328
|
+
}
|
package/src/notifications.ts
CHANGED
|
@@ -12,9 +12,9 @@ export const NotificationFrequencyContractSchema = z.enum([
|
|
|
12
12
|
export type NotificationFrequencyContract = z.infer<typeof NotificationFrequencyContractSchema>;
|
|
13
13
|
|
|
14
14
|
export const NotificationRuntimeStatusContractSchema = z.object({
|
|
15
|
-
provider: z.enum(["
|
|
15
|
+
provider: z.enum(["direct"]),
|
|
16
16
|
providerLabel: z.string().min(1),
|
|
17
|
-
mode: z.enum(["
|
|
17
|
+
mode: z.enum(["self_hosted", "preview"]),
|
|
18
18
|
canManagePreferences: z.boolean(),
|
|
19
19
|
canViewInbox: z.boolean(),
|
|
20
20
|
canMarkInboxRead: z.boolean(),
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/notifications.ts"],"sourcesContent":["import { z } from \"zod\";\n\nexport const NotificationChannelContractSchema = z.enum([\"in_app\", \"email\", \"push\", \"sms\", \"chat\"]);\nexport type NotificationChannelContract = z.infer<typeof NotificationChannelContractSchema>;\n\nexport const NotificationFrequencyContractSchema = z.enum([\n \"immediate\",\n \"daily\",\n \"weekly\",\n \"never\",\n]);\nexport type NotificationFrequencyContract = z.infer<typeof NotificationFrequencyContractSchema>;\n\nexport const NotificationRuntimeStatusContractSchema = z.object({\n provider: z.enum([\"novu\", \"direct\"]),\n providerLabel: z.string().min(1),\n mode: z.enum([\"managed\", \"self_hosted\", \"preview\", \"degraded\"]),\n canManagePreferences: z.boolean(),\n canViewInbox: z.boolean(),\n canMarkInboxRead: z.boolean(),\n summary: z.string().min(1),\n reason: z.string().optional(),\n missing: z.array(z.string()),\n});\nexport type NotificationRuntimeStatusContract = z.infer<\n typeof NotificationRuntimeStatusContractSchema\n>;\n\nexport const NotificationPreferenceContractSchema = z.object({\n userId: z.string().min(1),\n tenantId: z.string().min(1).optional(),\n channel: NotificationChannelContractSchema,\n enabled: z.boolean(),\n disabledCategories: z.array(z.string()).optional(),\n frequency: NotificationFrequencyContractSchema,\n updatedAt: z.string().datetime().optional(),\n});\nexport type NotificationPreferenceContract = z.infer<typeof NotificationPreferenceContractSchema>;\n\nexport const NotificationItemContractSchema = z.object({\n id: z.string().min(1),\n userId: z.string().min(1),\n tenantId: z.string().min(1).optional(),\n type: z.string().min(1),\n title: z.string(),\n body: z.string(),\n data: z.record(z.string(), z.unknown()).optional(),\n read: z.boolean(),\n createdAt: z.string().datetime(),\n updatedAt: z.string().datetime(),\n});\nexport type NotificationItemContract = z.infer<typeof NotificationItemContractSchema>;\n\nexport const NotificationListQueryContractSchema = z.object({\n limit: z.coerce.number().int().min(1).max(100).default(50),\n offset: z.coerce.number().int().min(0).default(0),\n unreadOnly: z.coerce.boolean().optional(),\n});\nexport type NotificationListQueryContract = z.infer<typeof NotificationListQueryContractSchema>;\n\nexport const NotificationListResponseContractSchema = z.object({\n items: z.array(NotificationItemContractSchema),\n total: z.number().int().nonnegative(),\n unreadCount: z.number().int().nonnegative(),\n});\nexport type NotificationListResponseContract = z.infer<\n typeof NotificationListResponseContractSchema\n>;\n\nexport const NotificationUnreadCountResponseContractSchema = z.object({\n count: z.number().int().nonnegative(),\n});\nexport type NotificationUnreadCountResponseContract = z.infer<\n typeof NotificationUnreadCountResponseContractSchema\n>;\n\nexport const NotificationMarkReadRequestContractSchema = z.object({\n ids: z.array(z.string().min(1)).min(1).max(100),\n});\nexport type NotificationMarkReadRequestContract = z.infer<\n typeof NotificationMarkReadRequestContractSchema\n>;\n\nexport const NotificationMutationCountResponseContractSchema = z.object({\n count: z.number().int().nonnegative(),\n});\nexport type NotificationMutationCountResponseContract = z.infer<\n typeof NotificationMutationCountResponseContractSchema\n>;\n\nexport const NotificationSettingsUpdateRequestContractSchema = z.object({\n type: z.string().min(1),\n channel: NotificationChannelContractSchema,\n enabled: z.boolean(),\n});\nexport type NotificationSettingsUpdateRequestContract = z.infer<\n typeof NotificationSettingsUpdateRequestContractSchema\n>;\n\nexport const NotificationSettingsUpdateResponseContractSchema = z.object({\n ok: z.literal(true),\n preference: NotificationPreferenceContractSchema,\n});\nexport type NotificationSettingsUpdateResponseContract = z.infer<\n typeof NotificationSettingsUpdateResponseContractSchema\n>;\n"],"mappings":"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","names":[]}
|