@sonicjs-cms/core 3.0.0-beta.2 → 3.0.0-beta.20
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/README.md +48 -49
- package/dist/admin-documents-form.template-DDSH6ROU.js +6 -0
- package/dist/{admin-documents-form.template-NLSI6Z42.js.map → admin-documents-form.template-DDSH6ROU.js.map} +1 -1
- package/dist/admin-documents-form.template-LSZKGA5J.cjs +19 -0
- package/dist/{admin-layout-catalyst.template-WHJGSWWD.js.map → admin-documents-form.template-LSZKGA5J.cjs.map} +1 -1
- package/dist/{filter-bar.template-DlVYMk-T.d.ts → admin-layout-catalyst.template-DrwDUfsE.d.cts} +25 -1
- package/dist/{filter-bar.template-DlVYMk-T.d.cts → admin-layout-catalyst.template-DrwDUfsE.d.ts} +25 -1
- package/dist/admin-layout-catalyst.template-KDHKVLXR.cjs +21 -0
- package/dist/{admin-layout-catalyst.template-ZK5HD545.cjs.map → admin-layout-catalyst.template-KDHKVLXR.cjs.map} +1 -1
- package/dist/admin-layout-catalyst.template-YQ4EMF2J.js +7 -0
- package/dist/{admin-documents-form.template-KN7JF66Q.cjs.map → admin-layout-catalyst.template-YQ4EMF2J.js.map} +1 -1
- package/dist/{app-Bo0X1OWX.d.ts → app-01M0dIwt.d.ts} +1 -1
- package/dist/{app-Do66yCcV.d.cts → app-aj39TGHB.d.cts} +1 -1
- package/dist/{chunk-ZEZ245PW.js → chunk-2XAQTPAE.js} +4 -236
- package/dist/chunk-2XAQTPAE.js.map +1 -0
- package/dist/{chunk-BDDABDAB.cjs → chunk-36Z3AKX3.cjs} +3 -239
- package/dist/chunk-36Z3AKX3.cjs.map +1 -0
- package/dist/{chunk-VXE42MYF.cjs → chunk-3E7IROND.cjs} +695 -428
- package/dist/chunk-3E7IROND.cjs.map +1 -0
- package/dist/{chunk-BLMTL57B.js → chunk-3TMTYJAJ.js} +26 -4
- package/dist/chunk-3TMTYJAJ.js.map +1 -0
- package/dist/{chunk-AAWNRBRB.cjs → chunk-4SHNHNRP.cjs} +95 -20
- package/dist/chunk-4SHNHNRP.cjs.map +1 -0
- package/dist/{chunk-QAYFOER6.cjs → chunk-5ARIHAGN.cjs} +285 -3
- package/dist/chunk-5ARIHAGN.cjs.map +1 -0
- package/dist/{chunk-XW56B23A.cjs → chunk-5RSB5SEK.cjs} +4 -4
- package/dist/{chunk-XW56B23A.cjs.map → chunk-5RSB5SEK.cjs.map} +1 -1
- package/dist/{chunk-VD2EA3WT.js → chunk-5UCMLBRQ.js} +328 -62
- package/dist/chunk-5UCMLBRQ.js.map +1 -0
- package/dist/{chunk-3TB6AT6X.js → chunk-5V62WT6M.js} +35 -4
- package/dist/chunk-5V62WT6M.js.map +1 -0
- package/dist/{chunk-LRZIAW7U.cjs → chunk-AQJEMVAY.cjs} +3 -3
- package/dist/chunk-AQJEMVAY.cjs.map +1 -0
- package/dist/{chunk-WULONYGB.cjs → chunk-CRGUD4KC.cjs} +9 -9
- package/dist/{chunk-WULONYGB.cjs.map → chunk-CRGUD4KC.cjs.map} +1 -1
- package/dist/{chunk-NLJVSER2.js → chunk-DSXEVMOM.js} +3 -2
- package/dist/chunk-DSXEVMOM.js.map +1 -0
- package/dist/{chunk-H2AXVCLS.cjs → chunk-DTGCXWWM.cjs} +141 -74
- package/dist/chunk-DTGCXWWM.cjs.map +1 -0
- package/dist/{chunk-NUKJ54GA.cjs → chunk-GMMCCIQO.cjs} +6 -6
- package/dist/{chunk-NUKJ54GA.cjs.map → chunk-GMMCCIQO.cjs.map} +1 -1
- package/dist/{chunk-6OUHGKFD.js → chunk-GMZ5TGYP.js} +3 -3
- package/dist/{chunk-6OUHGKFD.js.map → chunk-GMZ5TGYP.js.map} +1 -1
- package/dist/{chunk-6JQOUUOB.js → chunk-JQISFW6U.js} +3 -3
- package/dist/{chunk-6JQOUUOB.js.map → chunk-JQISFW6U.js.map} +1 -1
- package/dist/{chunk-NAVPFIG5.cjs → chunk-K623Q6WD.cjs} +35 -3
- package/dist/chunk-K623Q6WD.cjs.map +1 -0
- package/dist/{chunk-JEQ7FLOD.cjs → chunk-KIGVVO6N.cjs} +16 -10
- package/dist/chunk-KIGVVO6N.cjs.map +1 -0
- package/dist/{chunk-2CB4KY7I.cjs → chunk-LTZ5WYOK.cjs} +29 -7
- package/dist/chunk-LTZ5WYOK.cjs.map +1 -0
- package/dist/{chunk-YHSQVQXX.js → chunk-MYQ7KZUQ.js} +135 -68
- package/dist/chunk-MYQ7KZUQ.js.map +1 -0
- package/dist/{chunk-DNQCEKUK.cjs → chunk-N32OWET6.cjs} +5 -5
- package/dist/{chunk-DNQCEKUK.cjs.map → chunk-N32OWET6.cjs.map} +1 -1
- package/dist/{chunk-HDWE5FRJ.js → chunk-OBA2RYZN.js} +3 -3
- package/dist/{chunk-HDWE5FRJ.js.map → chunk-OBA2RYZN.js.map} +1 -1
- package/dist/{chunk-MVIZJOO5.cjs → chunk-PXNTCCPE.cjs} +8 -8
- package/dist/{chunk-MVIZJOO5.cjs.map → chunk-PXNTCCPE.cjs.map} +1 -1
- package/dist/{chunk-ZGGXCFR6.js → chunk-RDH6PUOP.js} +282 -4
- package/dist/chunk-RDH6PUOP.js.map +1 -0
- package/dist/{chunk-EF2NQUIQ.js → chunk-RMRJGMDE.js} +3 -3
- package/dist/{chunk-EF2NQUIQ.js.map → chunk-RMRJGMDE.js.map} +1 -1
- package/dist/{chunk-IVPRUGTY.js → chunk-SOZUG52O.js} +4 -4
- package/dist/{chunk-IVPRUGTY.js.map → chunk-SOZUG52O.js.map} +1 -1
- package/dist/{chunk-DSA4UX5B.cjs → chunk-TQG5FNNR.cjs} +3 -2
- package/dist/chunk-TQG5FNNR.cjs.map +1 -0
- package/dist/{chunk-GCDZZNIN.js → chunk-UWUP2VMT.js} +16 -10
- package/dist/chunk-UWUP2VMT.js.map +1 -0
- package/dist/{chunk-IESEVHXL.js → chunk-VVYVFCML.js} +12 -3
- package/dist/chunk-VVYVFCML.js.map +1 -0
- package/dist/{chunk-NMPEMSU4.js → chunk-W53J3BJ2.js} +3 -3
- package/dist/chunk-W53J3BJ2.js.map +1 -0
- package/dist/{chunk-RZ6H7OZK.js → chunk-WCA4VENG.js} +87 -12
- package/dist/chunk-WCA4VENG.js.map +1 -0
- package/dist/{chunk-HIKBY7MS.cjs → chunk-XWVDSM2L.cjs} +12 -3
- package/dist/chunk-XWVDSM2L.cjs.map +1 -0
- package/dist/{collection-config-JgHOpFCG.d.ts → collection-config-BTzAvKt2.d.cts} +25 -0
- package/dist/{collection-config-JgHOpFCG.d.cts → collection-config-BTzAvKt2.d.ts} +25 -0
- package/dist/config-6FB2BXMP.js +6 -0
- package/dist/{config-HFXANXCC.js.map → config-6FB2BXMP.js.map} +1 -1
- package/dist/config-OCH7S4WK.cjs +19 -0
- package/dist/{config-ON6FNMYX.cjs.map → config-OCH7S4WK.cjs.map} +1 -1
- package/dist/{define-plugin-BzNHc1ZI.d.ts → define-plugin-BYIey6sp.d.ts} +1 -1
- package/dist/{define-plugin-IWDKYaVm.d.cts → define-plugin-DsKiGu1q.d.cts} +1 -1
- package/dist/document-projection-4HG75S5S.js +4 -0
- package/dist/{document-projection-YYMC6I4U.js.map → document-projection-4HG75S5S.js.map} +1 -1
- package/dist/document-projection-JQHSTSFD.cjs +13 -0
- package/dist/{document-projection-TDWRJX3Z.cjs.map → document-projection-JQHSTSFD.cjs.map} +1 -1
- package/dist/index.cjs +928 -378
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +200 -12
- package/dist/index.d.ts +200 -12
- package/dist/index.js +612 -75
- package/dist/index.js.map +1 -1
- package/dist/middleware.cjs +37 -34
- package/dist/middleware.d.cts +2 -2
- package/dist/middleware.d.ts +2 -2
- package/dist/middleware.js +8 -5
- package/dist/migrations-HZJ6U6SX.js +4 -0
- package/dist/{migrations-WCAVBD7C.js.map → migrations-HZJ6U6SX.js.map} +1 -1
- package/dist/migrations-VQAFXMU7.cjs +13 -0
- package/dist/{migrations-NJJWQUKK.cjs.map → migrations-VQAFXMU7.cjs.map} +1 -1
- package/dist/{plugin-bootstrap-B8ThJU21.d.cts → plugin-bootstrap-BHWQ2df8.d.cts} +1 -1
- package/dist/{plugin-bootstrap-qu8hJgUt.d.ts → plugin-bootstrap-Bj4fxX1q.d.ts} +1 -1
- package/dist/plugins.cjs +40 -40
- package/dist/plugins.d.cts +2 -2
- package/dist/plugins.d.ts +2 -2
- package/dist/plugins.js +3 -3
- package/dist/rbac-7QZ4JZ2E.cjs +14 -0
- package/dist/{rbac-VONLJJKB.cjs.map → rbac-7QZ4JZ2E.cjs.map} +1 -1
- package/dist/rbac-Y43IEQOP.js +5 -0
- package/dist/{rbac-O73MFKDA.js.map → rbac-Y43IEQOP.js.map} +1 -1
- package/dist/routes.cjs +34 -34
- package/dist/routes.d.cts +2 -2
- package/dist/routes.d.ts +2 -2
- package/dist/routes.js +14 -14
- package/dist/services.cjs +42 -42
- package/dist/services.d.cts +16 -3
- package/dist/services.d.ts +16 -3
- package/dist/services.js +3 -3
- package/dist/{telemetry-B9vIV4wh.d.cts → telemetry-Cku1ax74.d.cts} +1 -1
- package/dist/{telemetry-B9vIV4wh.d.ts → telemetry-Cku1ax74.d.ts} +1 -1
- package/dist/templates.cjs +17 -17
- package/dist/templates.d.cts +2 -24
- package/dist/templates.d.ts +2 -24
- package/dist/templates.js +3 -3
- package/dist/{types-Dea1eNxU.d.ts → types-DT7XN5TX.d.cts} +1 -1
- package/dist/{types-Dea1eNxU.d.cts → types-DT7XN5TX.d.ts} +1 -1
- package/dist/types.d.cts +2 -2
- package/dist/types.d.ts +2 -2
- package/dist/utils.cjs +8 -8
- package/dist/utils.d.cts +2 -2
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +2 -2
- package/package.json +1 -1
- package/dist/admin-documents-form.template-KN7JF66Q.cjs +0 -19
- package/dist/admin-documents-form.template-NLSI6Z42.js +0 -6
- package/dist/admin-layout-catalyst.template-WHJGSWWD.js +0 -7
- package/dist/admin-layout-catalyst.template-ZK5HD545.cjs +0 -17
- package/dist/chunk-2CB4KY7I.cjs.map +0 -1
- package/dist/chunk-3TB6AT6X.js.map +0 -1
- package/dist/chunk-AAWNRBRB.cjs.map +0 -1
- package/dist/chunk-BDDABDAB.cjs.map +0 -1
- package/dist/chunk-BLMTL57B.js.map +0 -1
- package/dist/chunk-DSA4UX5B.cjs.map +0 -1
- package/dist/chunk-GCDZZNIN.js.map +0 -1
- package/dist/chunk-H2AXVCLS.cjs.map +0 -1
- package/dist/chunk-HIKBY7MS.cjs.map +0 -1
- package/dist/chunk-IESEVHXL.js.map +0 -1
- package/dist/chunk-JEQ7FLOD.cjs.map +0 -1
- package/dist/chunk-LRZIAW7U.cjs.map +0 -1
- package/dist/chunk-NAVPFIG5.cjs.map +0 -1
- package/dist/chunk-NLJVSER2.js.map +0 -1
- package/dist/chunk-NMPEMSU4.js.map +0 -1
- package/dist/chunk-QAYFOER6.cjs.map +0 -1
- package/dist/chunk-RZ6H7OZK.js.map +0 -1
- package/dist/chunk-VD2EA3WT.js.map +0 -1
- package/dist/chunk-VXE42MYF.cjs.map +0 -1
- package/dist/chunk-YHSQVQXX.js.map +0 -1
- package/dist/chunk-ZEZ245PW.js.map +0 -1
- package/dist/chunk-ZGGXCFR6.js.map +0 -1
- package/dist/config-HFXANXCC.js +0 -6
- package/dist/config-ON6FNMYX.cjs +0 -19
- package/dist/document-projection-TDWRJX3Z.cjs +0 -13
- package/dist/document-projection-YYMC6I4U.js +0 -4
- package/dist/migrations-NJJWQUKK.cjs +0 -13
- package/dist/migrations-WCAVBD7C.js +0 -4
- package/dist/rbac-O73MFKDA.js +0 -5
- package/dist/rbac-VONLJJKB.cjs +0 -14
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DocumentProjection, nanoid } from './chunk-
|
|
1
|
+
import { DocumentProjection, nanoid } from './chunk-UWUP2VMT.js';
|
|
2
2
|
|
|
3
3
|
// src/services/documents.ts
|
|
4
4
|
var DEFAULT_MAX_VERSIONS = 50;
|
|
@@ -47,6 +47,8 @@ var DocumentsService = class {
|
|
|
47
47
|
this.tenantId = opts.tenantId ?? "default";
|
|
48
48
|
this.versioning = opts.versioning ?? false;
|
|
49
49
|
}
|
|
50
|
+
db;
|
|
51
|
+
opts;
|
|
50
52
|
projection;
|
|
51
53
|
tenantId;
|
|
52
54
|
versioning;
|
|
@@ -370,7 +372,7 @@ var T_VERB = "rbac_verb";
|
|
|
370
372
|
var T_USER_ROLES = "rbac_user_roles";
|
|
371
373
|
var SYSTEM_RESOURCES = [
|
|
372
374
|
{ key: "*", label: "All resources", group: "system" },
|
|
373
|
-
{ key: "portal", label: "Admin
|
|
375
|
+
{ key: "portal", label: "Admin Panel", group: "system" },
|
|
374
376
|
{ key: "dashboard", label: "Dashboard", group: "system" },
|
|
375
377
|
{ key: "rbac", label: "Roles & Permissions", group: "system" },
|
|
376
378
|
{ key: "documents", label: "Documents", group: "system" },
|
|
@@ -385,6 +387,8 @@ var RbacService = class _RbacService {
|
|
|
385
387
|
this.db = db;
|
|
386
388
|
this.kv = kv;
|
|
387
389
|
}
|
|
390
|
+
db;
|
|
391
|
+
kv;
|
|
388
392
|
// Precedence for projecting the user's RBAC roles back onto the legacy
|
|
389
393
|
// users.role compat column (highest privilege first). Only `admin` is
|
|
390
394
|
// hardcoded as a seeded role — `editor` is listed here purely so that if an
|
|
@@ -728,6 +732,24 @@ var RbacService = class _RbacService {
|
|
|
728
732
|
{ resource: "document_type:*", verb: "delete" },
|
|
729
733
|
{ resource: "settings", verb: "read" }
|
|
730
734
|
]
|
|
735
|
+
},
|
|
736
|
+
{
|
|
737
|
+
id: "role-authenticated",
|
|
738
|
+
name: "authenticated",
|
|
739
|
+
displayName: "Authenticated",
|
|
740
|
+
description: "Signed-in users with no Admin Panel access",
|
|
741
|
+
isSystem: false,
|
|
742
|
+
grants: [
|
|
743
|
+
{ resource: "document_type:*", verb: "read" }
|
|
744
|
+
]
|
|
745
|
+
},
|
|
746
|
+
{
|
|
747
|
+
id: "role-public",
|
|
748
|
+
name: "public",
|
|
749
|
+
displayName: "Public",
|
|
750
|
+
description: "Unauthenticated visitors \u2014 read-only public content",
|
|
751
|
+
isSystem: false,
|
|
752
|
+
grants: []
|
|
731
753
|
}
|
|
732
754
|
];
|
|
733
755
|
const verbs = [
|
|
@@ -763,5 +785,5 @@ var RbacService = class _RbacService {
|
|
|
763
785
|
};
|
|
764
786
|
|
|
765
787
|
export { DocumentsService, RbacService, documentSecondsToMs };
|
|
766
|
-
//# sourceMappingURL=chunk-
|
|
767
|
-
//# sourceMappingURL=chunk-
|
|
788
|
+
//# sourceMappingURL=chunk-3TMTYJAJ.js.map
|
|
789
|
+
//# sourceMappingURL=chunk-3TMTYJAJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/services/documents.ts","../src/services/rbac.ts"],"names":[],"mappings":"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","file":"chunk-3TMTYJAJ.js","sourcesContent":["import { D1Database } from '@cloudflare/workers-types'\nimport { nanoid } from 'nanoid'\nimport type {\n Document,\n DocumentRow,\n CreateDocumentInput,\n UpdateDocumentInput,\n QueryableField,\n} from '../schemas/document'\nimport { DocumentProjection } from './document-projection'\n\nconst DEFAULT_MAX_VERSIONS = 50\n\n/**\n * D29: documents store `created_at`/`updated_at` in SECONDS (see `create`/`saveDraft`), but the legacy\n * `content` table — and therefore the public/CRUD `/api/content` contract — used MILLISECONDS. Any code\n * that shapes a document row into the content response must convert so `new Date(item.created_at)` keeps\n * working for API consumers. Null/undefined pass through unchanged.\n */\nexport function documentSecondsToMs(ts: number | null | undefined): number | null {\n return ts == null ? null : ts * 1000\n}\n\nfunction rowToDocument(row: DocumentRow): Document {\n return {\n id: row.id,\n rootId: row.root_id,\n typeId: row.type_id,\n typeVersion: row.type_version,\n versionOfId: row.version_of_id,\n versionNumber: row.version_number,\n isCurrentDraft: row.is_current_draft === 1,\n isPublished: row.is_published === 1,\n status: row.status,\n parentRootId: row.parent_root_id,\n slug: row.slug,\n path: row.path,\n title: row.title,\n zone: row.zone,\n sortOrder: row.sort_order,\n visible: row.visible === 1,\n publishedAt: row.published_at,\n scheduledAt: row.scheduled_at,\n expiresAt: row.expires_at,\n deletedAt: row.deleted_at,\n tenantId: row.tenant_id,\n locale: row.locale,\n translationGroupId: row.translation_group_id,\n data: JSON.parse(row.data),\n metadata: JSON.parse(row.metadata),\n ownerId: row.owner_id,\n createdBy: row.created_by,\n updatedBy: row.updated_by,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n }\n}\n\nexport interface DocumentsServiceOptions {\n queryableFields?: QueryableField[]\n typeSchemaVersion?: number\n maxVersionsPerRoot?: number\n /** Tenant this service operates within. Every root-keyed lookup is scoped to it (R3). POC default: 'default'. */\n tenantId?: string\n /** Retain version history (new row per saveDraft, supersede-as-history). Default false (in-place). */\n versioning?: boolean\n}\n\nexport class DocumentsService {\n private projection: DocumentProjection\n private tenantId: string\n private versioning: boolean\n\n constructor(\n private db: D1Database,\n private opts: DocumentsServiceOptions = {},\n ) {\n this.projection = new DocumentProjection(db)\n this.tenantId = opts.tenantId ?? 'default'\n this.versioning = opts.versioning ?? false\n }\n\n // ─── Create ───────────────────────────────────────────────────────────────\n\n async create(input: CreateDocumentInput, createdBy?: string): Promise<Document> {\n // D23: document timestamps are stored in SECONDS (legacy `content` rows use milliseconds). Any\n // Date() rendering of a document timestamp must multiply by 1000.\n const now = Math.floor(Date.now() / 1000)\n const id = nanoid()\n const publish = input.publishOnCreate ?? false\n // D34: backfill may carry the source row's original timestamps; normal creates default to now.\n const createdAt = input.createdAt ?? now\n const updatedAt = input.updatedAt ?? now\n\n const doc: Document = {\n id,\n rootId: id,\n typeId: input.typeId,\n typeVersion: this.opts.typeSchemaVersion ?? 1,\n versionOfId: null,\n versionNumber: 1,\n isCurrentDraft: true,\n isPublished: publish,\n status: publish ? 'published' : 'draft',\n parentRootId: input.parentRootId ?? '',\n slug: input.slug ?? null,\n path: null,\n title: input.title ?? null,\n zone: input.zone ?? null,\n sortOrder: input.sortOrder ?? 0,\n visible: input.visible ?? true,\n publishedAt: publish ? createdAt : null,\n scheduledAt: input.scheduledAt ?? null,\n expiresAt: input.expiresAt ?? null,\n deletedAt: null,\n // Tenant comes from the service scope unless the caller passes one explicitly. Never trust a\n // request-body tenant: route handlers must override with the resolved request-context tenant.\n tenantId: input.tenantId ?? this.tenantId,\n locale: input.locale ?? 'default',\n translationGroupId: '',\n data: input.data ?? {},\n metadata: input.metadata ?? {},\n ownerId: input.ownerId ?? null,\n createdBy: createdBy ?? null,\n updatedBy: createdBy ?? null,\n createdAt,\n updatedAt,\n }\n\n const insertDoc = this.db.prepare(\n `INSERT INTO documents (id, root_id, type_id, type_version, version_of_id, version_number,\n is_current_draft, is_published, status, parent_root_id, slug, path, title, zone,\n sort_order, visible, published_at, scheduled_at, expires_at, deleted_at,\n tenant_id, locale, translation_group_id, data, metadata,\n owner_id, created_by, updated_by, created_at, updated_at)\n VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`,\n ).bind(\n doc.id, doc.rootId, doc.typeId, doc.typeVersion, null, 1,\n 1, publish ? 1 : 0, doc.status, doc.parentRootId, doc.slug, null, doc.title, doc.zone,\n doc.sortOrder, doc.visible ? 1 : 0, doc.publishedAt, doc.scheduledAt, doc.expiresAt, null,\n doc.tenantId, doc.locale, '', JSON.stringify(doc.data), JSON.stringify(doc.metadata),\n doc.ownerId, doc.createdBy, doc.updatedBy, createdAt, updatedAt,\n )\n\n const derivedInserts = this.projection.buildDerivedInsertStatements(doc, this.opts.queryableFields ?? [], now)\n\n await this.db.batch([insertDoc, ...derivedInserts])\n return doc\n }\n\n // ─── Save new draft ───────────────────────────────────────────────────────\n // Atomically: demote previous draft → delete its derived rows (if not published) →\n // insert new draft → materialize derived rows → prune excess versions.\n\n async saveDraft(rootId: string, input: UpdateDocumentInput, updatedBy?: string): Promise<Document> {\n const now = Math.floor(Date.now() / 1000)\n const newId = nanoid()\n\n // Fetch current state synchronously before starting the batch. Tenant-scoped (R3): a service\n // for tenant B must not find or mutate tenant A's root.\n const prevDraftRow = await this.db\n .prepare('SELECT * FROM documents WHERE root_id = ? AND tenant_id = ? AND is_current_draft = 1')\n .bind(rootId, this.tenantId)\n .first<DocumentRow>()\n\n if (!prevDraftRow) throw new Error(`No current draft found for root ${rootId}`)\n\n const prevDraft = rowToDocument(prevDraftRow)\n\n const mergedData = { ...prevDraft.data, ...(input.data ?? {}) }\n const mergedMeta = { ...prevDraft.metadata, ...(input.metadata ?? {}) }\n\n const newDoc: Document = {\n ...prevDraft,\n id: newId,\n rootId,\n typeVersion: this.opts.typeSchemaVersion ?? prevDraft.typeVersion,\n versionOfId: prevDraft.id,\n versionNumber: 0, // computed by SQL below\n isCurrentDraft: true,\n isPublished: false,\n status: 'draft',\n slug: input.slug !== undefined ? input.slug ?? null : prevDraft.slug,\n title: input.title !== undefined ? input.title ?? null : prevDraft.title,\n zone: input.zone !== undefined ? input.zone ?? null : prevDraft.zone,\n sortOrder: input.sortOrder ?? prevDraft.sortOrder,\n visible: input.visible ?? prevDraft.visible,\n scheduledAt: input.scheduledAt !== undefined ? input.scheduledAt : prevDraft.scheduledAt,\n expiresAt: input.expiresAt !== undefined ? input.expiresAt : prevDraft.expiresAt,\n data: mergedData,\n metadata: mergedMeta,\n updatedBy: updatedBy ?? prevDraft.updatedBy,\n updatedAt: now,\n createdAt: now,\n }\n\n const prevIsPublished = prevDraftRow.is_published === 1\n\n // Versioning off + the working draft is a pure draft (not the live published row):\n // update it in place. No new row, no history accumulation. (R7: rebuild derived rows.)\n if (!this.versioning && !prevIsPublished) {\n return this.updateInPlace(prevDraft, input, now, updatedBy)\n }\n\n const statements: D1PreparedStatement[] = [\n // 1. Demote previous current draft FIRST (unique index: never two current drafts mid-batch).\n this.db.prepare('UPDATE documents SET is_current_draft = 0, updated_at = ? WHERE id = ? AND tenant_id = ?')\n .bind(now, prevDraft.id, this.tenantId),\n\n // 2. If the previous draft was not also the published row, delete its derived rows.\n ...(!prevIsPublished ? this.projection.buildDerivedDeleteStatements(prevDraft.id) : []),\n\n // 3. Insert new draft. version_number derived in SQL (COALESCE(MAX)+1 from existing rows).\n // R5 arithmetic — keep balanced: 30 columns = 5 leading '?' + 1 version_number subquery\n // + 3 literals (1,0,'draft') + 21 trailing '?'. Total placeholders: 5 + 1 (subquery\n // root_id) + 21 = 27, which MUST equal the 27 .bind() args below. Do not change one side\n // without recounting the other.\n this.db.prepare(\n `INSERT INTO documents (id, root_id, type_id, type_version, version_of_id, version_number,\n is_current_draft, is_published, status, parent_root_id, slug, path, title, zone,\n sort_order, visible, published_at, scheduled_at, expires_at, deleted_at,\n tenant_id, locale, translation_group_id, data, metadata,\n owner_id, created_by, updated_by, created_at, updated_at)\n SELECT ?,?,?,?,?,\n (SELECT COALESCE(MAX(version_number), 0) + 1 FROM documents WHERE root_id = ?),\n 1,0,'draft',?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?\n WHERE 1=1`,\n ).bind(\n newId, rootId, newDoc.typeId, newDoc.typeVersion, prevDraft.id,\n rootId,\n newDoc.parentRootId, newDoc.slug, null, newDoc.title, newDoc.zone,\n newDoc.sortOrder, newDoc.visible ? 1 : 0, null, newDoc.scheduledAt, newDoc.expiresAt, null,\n newDoc.tenantId, newDoc.locale, newDoc.translationGroupId,\n JSON.stringify(newDoc.data), JSON.stringify(newDoc.metadata),\n newDoc.ownerId, newDoc.createdBy, newDoc.updatedBy, now, now,\n ),\n\n // 4. Materialize derived rows for new draft.\n ...this.projection.buildDerivedInsertStatements(newDoc, this.opts.queryableFields ?? [], now),\n ]\n\n // 5. Prune excess versions (beyond maxVersionsPerRoot), never the published or current-draft row,\n // and never a version still referenced as version_of_id by another row (FK RESTRICT).\n const maxVersions = this.opts.maxVersionsPerRoot ?? DEFAULT_MAX_VERSIONS\n statements.push(\n this.db.prepare(\n `DELETE FROM documents WHERE root_id = ? AND tenant_id = ? AND is_current_draft = 0 AND is_published = 0\n AND id NOT IN (\n SELECT id FROM documents WHERE root_id = ? AND tenant_id = ? AND is_current_draft = 0 AND is_published = 0\n ORDER BY version_number DESC LIMIT ?\n )\n AND id NOT IN (SELECT version_of_id FROM documents WHERE version_of_id IS NOT NULL AND root_id = ? AND tenant_id = ?)`,\n ).bind(rootId, this.tenantId, rootId, this.tenantId, maxVersions, rootId, this.tenantId),\n )\n\n await this.db.batch(statements)\n\n // Fetch the saved row to get the SQL-computed version_number.\n const saved = await this.db\n .prepare('SELECT * FROM documents WHERE id = ?')\n .bind(newId)\n .first<DocumentRow>()\n return rowToDocument(saved!)\n }\n\n // In-place draft update (versioning off). Mutates the existing draft row; preserves id/root_id/\n // version_number/version_of_id and the is_current_draft/is_published flags. Rebuilds derived rows.\n private async updateInPlace(\n prevDraft: Document,\n input: UpdateDocumentInput,\n now: number,\n updatedBy?: string,\n ): Promise<Document> {\n const mergedData = { ...prevDraft.data, ...(input.data ?? {}) }\n const mergedMeta = { ...prevDraft.metadata, ...(input.metadata ?? {}) }\n\n const updated: Document = {\n ...prevDraft,\n slug: input.slug !== undefined ? input.slug ?? null : prevDraft.slug,\n title: input.title !== undefined ? input.title ?? null : prevDraft.title,\n zone: input.zone !== undefined ? input.zone ?? null : prevDraft.zone,\n sortOrder: input.sortOrder ?? prevDraft.sortOrder,\n visible: input.visible ?? prevDraft.visible,\n scheduledAt: input.scheduledAt !== undefined ? input.scheduledAt : prevDraft.scheduledAt,\n expiresAt: input.expiresAt !== undefined ? input.expiresAt : prevDraft.expiresAt,\n data: mergedData,\n metadata: mergedMeta,\n updatedBy: updatedBy ?? prevDraft.updatedBy,\n updatedAt: now,\n }\n\n const statements: D1PreparedStatement[] = [\n // R5: 11 SET '?' + 2 WHERE '?' (id, tenant_id) = 13 binds, matching .bind() below.\n this.db.prepare(\n `UPDATE documents SET\n slug = ?, title = ?, zone = ?, sort_order = ?, visible = ?,\n scheduled_at = ?, expires_at = ?, data = ?, metadata = ?, updated_by = ?, updated_at = ?\n WHERE id = ? AND tenant_id = ?`,\n ).bind(\n updated.slug, updated.title, updated.zone, updated.sortOrder, updated.visible ? 1 : 0,\n updated.scheduledAt, updated.expiresAt, JSON.stringify(updated.data), JSON.stringify(updated.metadata),\n updated.updatedBy, now,\n updated.id, this.tenantId,\n ),\n // R7: derived rows track the new data — delete then reinsert for this row.\n ...this.projection.buildDerivedDeleteStatements(updated.id),\n ...this.projection.buildDerivedInsertStatements(updated, this.opts.queryableFields ?? [], now),\n ]\n\n await this.db.batch(statements)\n\n const saved = await this.db.prepare('SELECT * FROM documents WHERE id = ?').bind(updated.id).first<DocumentRow>()\n return rowToDocument(saved!)\n }\n\n // ─── Publish ──────────────────────────────────────────────────────────────\n\n async publish(documentId: string, publishedBy?: string): Promise<Document> {\n const now = Math.floor(Date.now() / 1000)\n\n const targetRow = await this.db\n .prepare('SELECT * FROM documents WHERE id = ? AND tenant_id = ?')\n .bind(documentId, this.tenantId)\n .first<DocumentRow>()\n\n if (!targetRow) throw new Error(`Document ${documentId} not found`)\n\n const prevPublishedRow = await this.db\n .prepare('SELECT * FROM documents WHERE root_id = ? AND tenant_id = ? AND is_published = 1 AND id != ?')\n .bind(targetRow.root_id, this.tenantId, documentId)\n .first<DocumentRow>()\n\n const statements: D1PreparedStatement[] = []\n\n if (prevPublishedRow) {\n if (!this.versioning && prevPublishedRow.is_current_draft !== 1) {\n // Versioning off: old published row is pure history — remove it + its derived rows.\n // First null any version_of_id pointing at it (the target draft may chain off it) so the\n // delete can't trip the FK RESTRICT on documents.version_of_id (plan risk #1; the chain is\n // unused when versioning is off). Tenant-scoped (R3).\n statements.push(this.db.prepare('UPDATE documents SET version_of_id = NULL WHERE version_of_id = ? AND tenant_id = ?')\n .bind(prevPublishedRow.id, this.tenantId))\n statements.push(...this.projection.buildDerivedDeleteStatements(prevPublishedRow.id))\n statements.push(this.db.prepare('DELETE FROM documents WHERE id = ? AND tenant_id = ?')\n .bind(prevPublishedRow.id, this.tenantId))\n } else {\n // existing behavior: clear is_published, drop derived rows if not the current draft\n statements.push(\n this.db.prepare('UPDATE documents SET is_published = 0, updated_at = ? WHERE id = ?')\n .bind(now, prevPublishedRow.id),\n )\n if (prevPublishedRow.is_current_draft !== 1) {\n statements.push(...this.projection.buildDerivedDeleteStatements(prevPublishedRow.id))\n }\n }\n }\n\n // Set published on target row.\n statements.push(\n this.db.prepare(\n `UPDATE documents SET is_published = 1, status = 'published', published_at = ?, updated_at = ?, updated_by = ? WHERE id = ?`,\n ).bind(now, now, publishedBy ?? null, documentId),\n )\n\n // Ensure derived rows exist for the target (they do if it was current draft; materialize if not).\n if (targetRow.is_current_draft !== 1) {\n const targetDoc = rowToDocument(targetRow)\n statements.push(...this.projection.buildDerivedInsertStatements(targetDoc, this.opts.queryableFields ?? [], now))\n }\n\n await this.db.batch(statements)\n\n const saved = await this.db.prepare('SELECT * FROM documents WHERE id = ?').bind(documentId).first<DocumentRow>()\n return rowToDocument(saved!)\n }\n\n // ─── Unpublish ────────────────────────────────────────────────────────────\n\n async unpublish(documentId: string): Promise<Document> {\n const now = Math.floor(Date.now() / 1000)\n\n const row = await this.db\n .prepare('SELECT * FROM documents WHERE id = ? AND tenant_id = ?')\n .bind(documentId, this.tenantId)\n .first<DocumentRow>()\n\n if (!row) throw new Error(`Document ${documentId} not found`)\n if (!row.is_published) throw new Error(`Document ${documentId} is not published`)\n\n const statements: D1PreparedStatement[] = [\n this.db.prepare(`UPDATE documents SET is_published = 0, status = 'draft', updated_at = ? WHERE id = ?`)\n .bind(now, documentId),\n ]\n\n // If the unpublished row is not the current draft, remove its derived rows.\n if (row.is_current_draft !== 1) {\n statements.push(...this.projection.buildDerivedDeleteStatements(documentId))\n }\n\n await this.db.batch(statements)\n\n const saved = await this.db.prepare('SELECT * FROM documents WHERE id = ?').bind(documentId).first<DocumentRow>()\n return rowToDocument(saved!)\n }\n\n // ─── Soft delete ──────────────────────────────────────────────────────────\n\n async softDelete(documentId: string): Promise<void> {\n const now = Math.floor(Date.now() / 1000)\n await this.db\n .prepare('UPDATE documents SET deleted_at = ?, updated_at = ? WHERE id = ? AND tenant_id = ?')\n .bind(now, now, documentId, this.tenantId)\n .run()\n }\n\n // ─── Hard erase (PII types) ───────────────────────────────────────────────\n // Deletes every version row for a root plus all derived data, in dependency order.\n\n async erase(rootId: string, tenantId: string): Promise<void> {\n // Get all document IDs for this root.\n const result = await this.db\n .prepare('SELECT id FROM documents WHERE root_id = ? AND tenant_id = ?')\n .bind(rootId, tenantId)\n .all<{ id: string }>()\n\n const docIds = (result.results ?? []).map(r => r.id)\n if (docIds.length === 0) return\n\n const statements: D1PreparedStatement[] = []\n\n // Delete derived tables first (explicit; don't rely on FK cascade).\n for (const id of docIds) {\n statements.push(this.db.prepare('DELETE FROM document_facets WHERE document_id = ?').bind(id))\n statements.push(this.db.prepare('DELETE FROM document_references WHERE from_document_id = ?').bind(id))\n }\n\n statements.push(this.db.prepare('DELETE FROM document_permissions WHERE root_id = ? AND tenant_id = ?').bind(rootId, tenantId))\n\n // Delete all version rows.\n for (const id of docIds) {\n statements.push(this.db.prepare('DELETE FROM documents WHERE id = ?').bind(id))\n }\n\n await this.db.batch(statements)\n }\n}\n","/**\n * Dynamic RBAC service — document-backed.\n *\n * Roles, verbs, and user-role assignments are stored as `is_auth` documents\n * (slug-addressed) instead of relational tables:\n * rbac_role slug = roleId, data = { name, displayName, description, isSystem, grants:[{resource,verb,scope}] }\n * rbac_verb slug = verbId, data = { name, description, isSystem, sortOrder }\n * rbac_user_roles slug = userId, data = { roleIds:[] }\n * Grants are embedded in the role document (no separate join type); user-role\n * assignments are embedded in a per-user document. Resources are still computed:\n * a fixed set of system resources plus one `document_type:<name>` per type.\n *\n * Wildcards: resource '*' / 'document_type:*', verb '*' / 'manage' (implies all).\n * Scope: 'any' beats 'own' beats 'none'.\n *\n * The public API is unchanged from the relational implementation, so callers\n * (admin-rbac routes, permission checks) need no changes.\n */\nimport { DocumentsService } from './documents'\n\nexport interface RbacRole {\n id: string\n name: string\n display_name: string\n description: string | null\n is_system: number\n}\nexport interface RbacVerb {\n id: string\n name: string\n description: string | null\n is_system: number\n sort_order: number\n}\nexport interface RbacResource {\n key: string // e.g. 'content' or 'collection:blog_posts'\n label: string\n group: 'system' | 'document_type'\n}\nexport type PermissionScope = 'none' | 'own' | 'any'\nexport interface Grant {\n role_id: string\n resource: string\n verb: string\n scope: Exclude<PermissionScope, 'none'>\n}\n\ninterface GrantData { resource: string; verb: string; scope?: PermissionScope }\ninterface RoleData { name: string; displayName: string; description?: string | null; isSystem?: boolean; grants?: GrantData[] }\ninterface VerbData { name: string; description?: string | null; isSystem?: boolean; sortOrder?: number }\ninterface UserRolesData { roleIds?: string[] }\ninterface DocRow { id: string; root_id: string; slug: string | null; data: string }\n\nconst TENANT = 'default'\nconst T_ROLE = 'rbac_role'\nconst T_VERB = 'rbac_verb'\nconst T_USER_ROLES = 'rbac_user_roles'\n\nconst SYSTEM_RESOURCES: RbacResource[] = [\n { key: '*', label: 'All resources', group: 'system' },\n { key: 'portal', label: 'Admin Panel', group: 'system' },\n { key: 'dashboard', label: 'Dashboard', group: 'system' },\n { key: 'rbac', label: 'Roles & Permissions', group: 'system' },\n { key: 'documents', label: 'Documents', group: 'system' as const },\n { key: 'document_types', label: 'Document Types', group: 'system' as const },\n { key: 'email', label: 'Email Management', group: 'system' },\n { key: 'users', label: 'Users', group: 'system' },\n { key: 'settings', label: 'Settings', group: 'system' },\n { key: 'logs', label: 'Logs', group: 'system' },\n]\n\nexport class RbacService {\n // Precedence for projecting the user's RBAC roles back onto the legacy\n // users.role compat column (highest privilege first). Only `admin` is\n // hardcoded as a seeded role — `editor` is listed here purely so that if an\n // administrator chooses to recreate a role named `editor`, legacy code that\n // still gates on the `editor` label keeps working.\n private static readonly LEGACY_ROLE_PRECEDENCE = ['admin', 'editor']\n\n private _docs?: DocumentsService\n\n constructor(private db: D1Database, private kv?: KVNamespace) {}\n\n // ── Document access helpers ──────────────────────────────────────────────────\n\n private docs(): DocumentsService {\n if (!this._docs) {\n this._docs = new DocumentsService(this.db, { tenantId: TENANT, maxVersionsPerRoot: 1, queryableFields: [] })\n }\n return this._docs\n }\n\n private parse<T>(row: DocRow): { id: string; rootId: string; slug: string; data: T } {\n let data: T\n try { data = JSON.parse(row.data) as T } catch { data = {} as T }\n return { id: row.id, rootId: row.root_id, slug: row.slug ?? '', data }\n }\n\n private async listDocs<T>(typeId: string): Promise<Array<{ id: string; rootId: string; slug: string; data: T }>> {\n const res = await this.db\n .prepare(\n `SELECT id, root_id, slug, data FROM documents\n WHERE type_id = ? AND tenant_id = ? AND is_current_draft = 1 AND deleted_at IS NULL`,\n )\n .bind(typeId, TENANT)\n .all<DocRow>()\n return (res.results ?? []).map((r) => this.parse<T>(r))\n }\n\n private async getDoc<T>(typeId: string, slug: string): Promise<{ id: string; rootId: string; data: T } | null> {\n const row = await this.db\n .prepare(\n `SELECT id, root_id, slug, data FROM documents\n WHERE type_id = ? AND tenant_id = ? AND slug = ? AND is_current_draft = 1 AND deleted_at IS NULL`,\n )\n .bind(typeId, TENANT, slug)\n .first<DocRow>()\n return row ? this.parse<T>(row) : null\n }\n\n private async upsertDoc(typeId: string, slug: string, data: unknown, title: string | null): Promise<void> {\n const existing = await this.db\n .prepare(\n `SELECT root_id FROM documents\n WHERE type_id = ? AND tenant_id = ? AND slug = ? AND is_current_draft = 1 AND deleted_at IS NULL`,\n )\n .bind(typeId, TENANT, slug)\n .first<{ root_id: string }>()\n const payload = data as Record<string, unknown>\n if (existing?.root_id) {\n await this.docs().saveDraft(existing.root_id, { data: payload, title })\n } else {\n await this.docs().create({\n typeId,\n tenantId: TENANT,\n locale: 'default',\n parentRootId: '',\n slug,\n title,\n sortOrder: 0,\n visible: true,\n data: payload,\n metadata: {},\n ownerId: null,\n publishOnCreate: false,\n })\n }\n }\n\n private async deleteDoc(typeId: string, slug: string): Promise<void> {\n const doc = await this.getDoc(typeId, slug)\n if (doc) await this.docs().softDelete(doc.id)\n }\n\n private roleToRow(d: { slug: string; data: RoleData }): RbacRole {\n return {\n id: d.slug,\n name: d.data.name,\n display_name: d.data.displayName,\n description: d.data.description ?? null,\n is_system: d.data.isSystem ? 1 : 0,\n }\n }\n\n // ── Reads ────────────────────────────────────────────────────────────────────\n\n async getRoles(): Promise<RbacRole[]> {\n const docs = await this.listDocs<RoleData>(T_ROLE)\n return docs\n .map((d) => this.roleToRow(d))\n .sort((a, b) => b.is_system - a.is_system || a.name.localeCompare(b.name))\n }\n\n async getVerbs(): Promise<RbacVerb[]> {\n const docs = await this.listDocs<VerbData>(T_VERB)\n return docs\n .map((d) => ({\n id: d.slug,\n name: d.data.name,\n description: d.data.description ?? null,\n is_system: d.data.isSystem ? 1 : 0,\n sort_order: d.data.sortOrder ?? 100,\n }))\n .sort((a, b) => a.sort_order - b.sort_order || a.name.localeCompare(b.name))\n }\n\n /** System resources + one `document_type:<name>` per active document type. */\n async getResources(): Promise<RbacResource[]> {\n const types = (\n await this.db\n .prepare('SELECT name, display_name FROM document_types WHERE is_active = 1 ORDER BY name')\n .all<{ name: string; display_name: string }>()\n ).results as Array<{ name: string; display_name: string }>\n const documentTypeResources: RbacResource[] = [\n { key: 'document_type:*', label: 'All document types', group: 'document_type' },\n ...types.map((t) => ({\n key: `document_type:${t.name}`,\n label: t.display_name || t.name,\n group: 'document_type' as const,\n })),\n ]\n return [...SYSTEM_RESOURCES, ...documentTypeResources]\n }\n\n async getGrants(): Promise<Grant[]> {\n const roles = await this.listDocs<RoleData>(T_ROLE)\n const out: Grant[] = []\n for (const r of roles) {\n for (const g of r.data.grants ?? []) {\n out.push({ role_id: r.slug, resource: g.resource, verb: g.verb, scope: g.scope === 'own' ? 'own' : 'any' })\n }\n }\n return out\n }\n\n async getRolesForUser(userId: string): Promise<RbacRole[]> {\n const ur = await this.getDoc<UserRolesData>(T_USER_ROLES, userId)\n const roleIds = new Set(ur?.data.roleIds ?? [])\n if (roleIds.size === 0) return []\n const roles = await this.listDocs<RoleData>(T_ROLE)\n return roles.filter((r) => roleIds.has(r.slug)).map((d) => this.roleToRow(d))\n }\n\n /** Grants attached to a set of role ids (from the embedded role grants). */\n private async grantsForRoleIds(roleIds: string[]): Promise<Array<{ resource: string; verb: string; scope: PermissionScope }>> {\n if (roleIds.length === 0) return []\n const want = new Set(roleIds)\n const roles = await this.listDocs<RoleData>(T_ROLE)\n const out: Array<{ resource: string; verb: string; scope: PermissionScope }> = []\n for (const r of roles) {\n if (!want.has(r.slug)) continue\n for (const g of r.data.grants ?? []) {\n out.push({ resource: g.resource, verb: g.verb, scope: g.scope === 'own' ? 'own' : 'any' })\n }\n }\n return out\n }\n\n /** Does a single grant row satisfy the requested (resource, verb)? */\n private grantMatches(g: { resource: string; verb: string }, resource: string, verb: string): boolean {\n const resourceOk =\n g.resource === '*' ||\n g.resource === resource ||\n (g.resource === 'document_type:*' && resource.startsWith('document_type:'))\n if (!resourceOk) return false\n return g.verb === '*' || g.verb === verb || g.verb === 'manage'\n }\n\n private strongestScope(scopes: PermissionScope[]): PermissionScope {\n if (scopes.includes('any')) return 'any'\n if (scopes.includes('own')) return 'own'\n return 'none'\n }\n\n /** Can the user perform `verb` on `resource`? Reads the live grant matrix. */\n async can(userId: string, resource: string, verb: string): Promise<boolean> {\n return (await this.getPermissionScope(userId, resource, verb)) !== 'none'\n }\n\n /** Highest scope granted to the user for `resource:verb`. */\n async getPermissionScope(userId: string, resource: string, verb: string): Promise<PermissionScope> {\n const ur = await this.getDoc<UserRolesData>(T_USER_ROLES, userId)\n const grants = await this.grantsForRoleIds(ur?.data.roleIds ?? [])\n return this.strongestScope(\n grants.filter((g) => this.grantMatches(g, resource, verb)).map((g) => (g.scope === 'own' ? 'own' : 'any')),\n )\n }\n\n /** Flattened, human-readable permission list for a user. Cached in KV for 60 s. */\n async permissionsForUser(userId: string): Promise<string[]> {\n if (this.kv) {\n const cached = await this.kv.get(`rbac:perms:${userId}`)\n if (cached !== null) return JSON.parse(cached) as string[]\n }\n const ur = await this.getDoc<UserRolesData>(T_USER_ROLES, userId)\n const roleIds = ur?.data.roleIds ?? []\n if (roleIds.length === 0) return []\n const grants = await this.grantsForRoleIds(roleIds)\n const resources = await this.getResources()\n const verbs = await this.getVerbs()\n const out = new Set<string>()\n for (const r of resources) {\n for (const v of verbs) {\n if (grants.some((g) => this.grantMatches(g, r.key, v.name))) out.add(`${r.key}:${v.name}`)\n }\n }\n const result = [...out].sort()\n if (this.kv) {\n await this.kv.put(`rbac:perms:${userId}`, JSON.stringify(result), { expirationTtl: 60 })\n }\n return result\n }\n\n // ── Mutations ──────────────────────────────────────────────────────────────\n\n async createRole(name: string, displayName: string, description = ''): Promise<void> {\n const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, '-')\n const id = `role-${slug}`\n await this.upsertDoc(\n T_ROLE,\n id,\n { name: name.toLowerCase(), displayName, description, isSystem: false, grants: [] } satisfies RoleData,\n displayName,\n )\n }\n\n async deleteRole(roleId: string): Promise<void> {\n const role = await this.getDoc<RoleData>(T_ROLE, roleId)\n if (!role || role.data.isSystem) return // System roles cannot be deleted.\n await this.deleteDoc(T_ROLE, roleId)\n }\n\n /**\n * Update a role's display name and description. The `name` (slug) can only be\n * changed for custom roles — system role names are referenced by the legacy\n * mapping, so they stay fixed.\n */\n async updateRole(roleId: string, displayName: string, description = '', name?: string): Promise<void> {\n const role = await this.getDoc<RoleData>(T_ROLE, roleId)\n if (!role) return\n const next: RoleData = { ...role.data, displayName, description }\n if (!role.data.isSystem && name) {\n next.name = name.toLowerCase().replace(/[^a-z0-9]+/g, '-')\n }\n await this.upsertDoc(T_ROLE, roleId, next, displayName)\n }\n\n /** Update displayName + portal access in a single write to avoid double-saveDraft FK issues. */\n async updateRoleAndPortalAccess(\n roleId: string,\n displayName: string,\n name: string | undefined,\n portalEnabled: boolean,\n description?: string,\n ): Promise<void> {\n const role = await this.getDoc<RoleData>(T_ROLE, roleId)\n if (!role) return\n const next: RoleData = { ...role.data, displayName, description: description ?? role.data.description ?? '' }\n if (!role.data.isSystem && name) {\n next.name = name.toLowerCase().replace(/[^a-z0-9]+/g, '-')\n }\n const grants = (next.grants ?? []).filter((g) => !(g.resource === 'portal' && g.verb === 'access'))\n if (portalEnabled) grants.push({ resource: 'portal', verb: 'access', scope: 'any' })\n next.grants = grants\n await this.upsertDoc(T_ROLE, roleId, next, displayName)\n }\n\n async createVerb(name: string, description = ''): Promise<void> {\n const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, '-')\n const id = `verb-${slug}`\n await this.upsertDoc(\n T_VERB,\n id,\n { name: name.toLowerCase(), description, isSystem: false, sortOrder: 100 } satisfies VerbData,\n name,\n )\n }\n\n async deleteVerb(verbId: string): Promise<void> {\n const verb = await this.getDoc<VerbData>(T_VERB, verbId)\n if (!verb || verb.data.isSystem) return\n await this.deleteDoc(T_VERB, verbId)\n }\n\n /** Replace all grants for one role with the supplied (resource, verb, scope) rows. */\n async setRoleGrants(\n roleId: string,\n pairs: Array<{ resource: string; verb: string; scope?: Exclude<PermissionScope, 'none'> }>,\n ): Promise<void> {\n const role = await this.getDoc<RoleData>(T_ROLE, roleId)\n if (!role) return\n const grants: GrantData[] = pairs.map((p) => ({ resource: p.resource, verb: p.verb, scope: p.scope === 'own' ? 'own' : 'any' }))\n await this.upsertDoc(T_ROLE, roleId, { ...role.data, grants } satisfies RoleData, role.data.displayName)\n }\n\n /**\n * Count active users (optionally excluding one) who hold BOTH an effective\n * portal:access grant and an effective rbac:manage grant — the users who could\n * recover from a permission lockout. Powers the self-lockout guard.\n */\n async countPortalAdmins(excludeUserId?: string): Promise<number> {\n const active = (\n await this.db.prepare('SELECT id FROM auth_user WHERE is_active = 1').all<{ id: string }>()\n ).results as Array<{ id: string }>\n const activeIds = new Set(active.map((u) => u.id))\n\n // role id -> its grants\n const roles = await this.listDocs<RoleData>(T_ROLE)\n const grantsByRole = new Map<string, GrantData[]>(roles.map((r) => [r.slug, r.data.grants ?? []]))\n\n const userRoles = await this.listDocs<UserRolesData>(T_USER_ROLES)\n let count = 0\n for (const ur of userRoles) {\n const userId = ur.slug\n if (!activeIds.has(userId)) continue\n if (excludeUserId && userId === excludeUserId) continue\n let portal = false\n let rbac = false\n for (const rid of ur.data.roleIds ?? []) {\n for (const g of grantsByRole.get(rid) ?? []) {\n if (this.grantMatches(g, 'portal', 'access')) portal = true\n if (this.grantMatches(g, 'rbac', 'manage')) rbac = true\n }\n }\n if (portal && rbac) count++\n }\n return count\n }\n\n /**\n * Replace a user's RBAC role assignments. The `rbac_user_roles` document is the\n * single source of truth for authorization; the legacy `auth_user.role` column\n * is kept as a derived projection (highest-precedence system role, else\n * 'viewer') so the two never diverge.\n */\n async setUserRoles(userId: string, roleIds: string[]): Promise<void> {\n const allRoles = await this.listDocs<RoleData>(T_ROLE)\n const byId = new Map(allRoles.map((r) => [r.slug, r.data]))\n const names = roleIds.map((id) => byId.get(id)?.name).filter((n): n is string => !!n)\n const primaryRole = RbacService.LEGACY_ROLE_PRECEDENCE.find((r) => names.includes(r)) || 'viewer'\n\n // Self-lockout guard: never leave zero active users who can BOTH enter the\n // portal and manage RBAC (the minimum needed to recover).\n const newGrants: GrantData[] = []\n for (const id of roleIds) for (const g of byId.get(id)?.grants ?? []) newGrants.push(g)\n const userWillBeAdmin =\n newGrants.some((g) => this.grantMatches(g, 'portal', 'access')) &&\n newGrants.some((g) => this.grantMatches(g, 'rbac', 'manage'))\n if (!userWillBeAdmin && (await this.countPortalAdmins(userId)) === 0) {\n throw new Error(\n 'Refusing to update roles: this would leave no user able to manage Roles & Permissions and access the portal. Grant another user portal access + Roles & Permissions first.',\n )\n }\n\n await this.upsertDoc(T_USER_ROLES, userId, { roleIds } satisfies UserRolesData, null)\n // Keep the legacy auth_user.role column in lockstep as a projection of RBAC.\n await this.db.prepare('UPDATE auth_user SET role = ?, updated_at = ? WHERE id = ?').bind(primaryRole, Date.now(), userId).run()\n if (this.kv) await this.kv.delete(`rbac:perms:${userId}`)\n }\n\n async setRolePortalAccess(roleId: string, enabled: boolean): Promise<void> {\n const role = await this.getDoc<RoleData>(T_ROLE, roleId)\n if (!role) return\n const grants = (role.data.grants ?? []).filter((g) => !(g.resource === 'portal' && g.verb === 'access'))\n if (enabled) grants.push({ resource: 'portal', verb: 'access', scope: 'any' })\n await this.upsertDoc(T_ROLE, roleId, { ...role.data, grants } satisfies RoleData, role.data.displayName)\n }\n\n // ── Bootstrap helpers ────────────────────────────────────────────────────────\n\n /**\n * Seed the system roles, verbs, and their grants as documents. Idempotent —\n * existing roles/verbs (by slug) are left untouched. Replaces the INSERT OR\n * IGNORE seeds that lived in migration 0001. Call at bootstrap, after the rbac\n * document types are registered.\n */\n async ensureSystemRbacSeed(): Promise<void> {\n // `admin` is the only hardcoded SYSTEM role (locked, undeletable). `editor`\n // is seeded as a non-system example so a fresh install has a usable second\n // role out of the box, but an administrator can edit, rename, or delete it.\n const roles: Array<RoleData & { id: string }> = [\n { id: 'role-admin', name: 'admin', displayName: 'Administrator', description: 'Full access to everything', isSystem: true,\n grants: [\n { resource: '*', verb: 'manage' }, { resource: 'portal', verb: 'access' }, { resource: 'rbac', verb: 'manage' },\n { resource: 'document_types', verb: 'manage' }, { resource: 'email', verb: 'manage' }, { resource: 'users', verb: 'manage' },\n ] },\n { id: 'role-editor', name: 'editor', displayName: 'Editor', description: 'Manage documents across all types', isSystem: false,\n grants: [\n { resource: 'portal', verb: 'access' },\n { resource: 'documents', verb: 'manage' },\n { resource: 'document_type:*', verb: 'read' },\n { resource: 'document_type:*', verb: 'create' },\n { resource: 'document_type:*', verb: 'update' },\n { resource: 'document_type:*', verb: 'delete' },\n { resource: 'settings', verb: 'read' },\n ] },\n { id: 'role-authenticated', name: 'authenticated', displayName: 'Authenticated', description: 'Signed-in users with no Admin Panel access', isSystem: false,\n grants: [\n { resource: 'document_type:*', verb: 'read' },\n ] },\n { id: 'role-public', name: 'public', displayName: 'Public', description: 'Unauthenticated visitors — read-only public content', isSystem: false,\n grants: [] },\n ]\n const verbs: Array<VerbData & { id: string }> = [\n { id: 'verb-access', name: 'access', description: 'Enter or use a portal/resource', isSystem: true, sortOrder: 5 },\n { id: 'verb-read', name: 'read', description: 'View a resource', isSystem: true, sortOrder: 10 },\n { id: 'verb-create', name: 'create', description: 'Create a resource', isSystem: true, sortOrder: 20 },\n { id: 'verb-update', name: 'update', description: 'Edit a resource', isSystem: true, sortOrder: 30 },\n { id: 'verb-delete', name: 'delete', description: 'Remove a resource', isSystem: true, sortOrder: 40 },\n { id: 'verb-manage', name: 'manage', description: 'Full control (implies all verbs)', isSystem: true, sortOrder: 50 },\n ]\n\n for (const r of roles) {\n if (await this.getDoc(T_ROLE, r.id)) continue\n const { id, ...data } = r\n await this.upsertDoc(T_ROLE, id, data, r.displayName)\n }\n for (const v of verbs) {\n if (await this.getDoc(T_VERB, v.id)) continue\n const { id, ...data } = v\n await this.upsertDoc(T_VERB, id, data, v.name)\n }\n }\n\n /** Assign a role to a user by role name (e.g. 'admin'), preserving existing roles. */\n async addUserRoleByName(userId: string, roleName: string): Promise<void> {\n const roles = await this.listDocs<RoleData>(T_ROLE)\n const role = roles.find((r) => r.data.name === roleName.toLowerCase())\n if (!role) return\n const ur = await this.getDoc<UserRolesData>(T_USER_ROLES, userId)\n const roleIds = new Set(ur?.data.roleIds ?? [])\n if (roleIds.has(role.slug)) return\n roleIds.add(role.slug)\n await this.setUserRoles(userId, [...roleIds])\n }\n}\n"]}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
3
|
+
var chunkLTZ5WYOK_cjs = require('./chunk-LTZ5WYOK.cjs');
|
|
4
|
+
var chunk5ARIHAGN_cjs = require('./chunk-5ARIHAGN.cjs');
|
|
5
|
+
var chunkTQG5FNNR_cjs = require('./chunk-TQG5FNNR.cjs');
|
|
6
|
+
var chunkK623Q6WD_cjs = require('./chunk-K623Q6WD.cjs');
|
|
6
7
|
var chunkJ6JTWD2A_cjs = require('./chunk-J6JTWD2A.cjs');
|
|
7
8
|
var chunkRCQ2HIQD_cjs = require('./chunk-RCQ2HIQD.cjs');
|
|
9
|
+
var chunkAQJEMVAY_cjs = require('./chunk-AQJEMVAY.cjs');
|
|
8
10
|
var zod = require('zod');
|
|
9
11
|
var jwt = require('hono/jwt');
|
|
10
12
|
var cookie = require('hono/cookie');
|
|
@@ -33,6 +35,7 @@ var DocumentTypeRegistry = class {
|
|
|
33
35
|
constructor(db) {
|
|
34
36
|
this.db = db;
|
|
35
37
|
}
|
|
38
|
+
db;
|
|
36
39
|
cache = /* @__PURE__ */ new Map();
|
|
37
40
|
// Register or update a document type. Idempotent: bumps schema_version only when schema changes.
|
|
38
41
|
async register(def) {
|
|
@@ -69,7 +72,7 @@ var DocumentTypeRegistry = class {
|
|
|
69
72
|
now,
|
|
70
73
|
def.id
|
|
71
74
|
).run();
|
|
72
|
-
await
|
|
75
|
+
await chunkTQG5FNNR_cjs.ensureScalarSchema(this.db, def.id, def.queryableFields ?? []);
|
|
73
76
|
const updated = await this.findById(def.id);
|
|
74
77
|
this.cache.set(def.id, updated);
|
|
75
78
|
return updated;
|
|
@@ -91,7 +94,7 @@ var DocumentTypeRegistry = class {
|
|
|
91
94
|
now,
|
|
92
95
|
now
|
|
93
96
|
).run();
|
|
94
|
-
await
|
|
97
|
+
await chunkTQG5FNNR_cjs.ensureScalarSchema(this.db, def.id, def.queryableFields ?? []);
|
|
95
98
|
const created = await this.findById(def.id);
|
|
96
99
|
this.cache.set(def.id, created);
|
|
97
100
|
return created;
|
|
@@ -267,6 +270,26 @@ async function bootstrapDocumentTypes(db) {
|
|
|
267
270
|
{ name: "blocked", kind: "scalar", type: "integer", column: "q_sa_blocked" }
|
|
268
271
|
]
|
|
269
272
|
});
|
|
273
|
+
await registry.register({
|
|
274
|
+
id: "api_key",
|
|
275
|
+
name: "api_key",
|
|
276
|
+
displayName: "API Key",
|
|
277
|
+
description: "Programmatic API access key (auth-owned; only the secret hash is stored)",
|
|
278
|
+
source: "system",
|
|
279
|
+
isAuth: true,
|
|
280
|
+
schema: anyObject,
|
|
281
|
+
settings: {
|
|
282
|
+
internal: true,
|
|
283
|
+
maxVersionsPerRoot: 1,
|
|
284
|
+
pii: true,
|
|
285
|
+
baseGrants: { admin: ["read", "create", "update", "delete", "manage"] }
|
|
286
|
+
},
|
|
287
|
+
queryableFields: [
|
|
288
|
+
{ name: "keyHash", kind: "scalar", type: "text", column: "q_apikey_hash" },
|
|
289
|
+
{ name: "userId", kind: "scalar", type: "text", column: "q_apikey_user_id" },
|
|
290
|
+
{ name: "revoked", kind: "scalar", type: "integer", column: "q_apikey_revoked" }
|
|
291
|
+
]
|
|
292
|
+
});
|
|
270
293
|
await registry.register({
|
|
271
294
|
id: "analytics_event",
|
|
272
295
|
name: "analytics_event",
|
|
@@ -329,12 +352,18 @@ async function bootstrapDocumentTypes(db) {
|
|
|
329
352
|
}
|
|
330
353
|
async function autoRegisterCollectionDocumentTypes(db) {
|
|
331
354
|
const registry = new DocumentTypeRegistry(db);
|
|
332
|
-
const collections =
|
|
355
|
+
const collections = chunk5ARIHAGN_cjs.getCollectionRegistry().listActive();
|
|
333
356
|
const registered = [];
|
|
334
357
|
for (const collection of collections) {
|
|
335
358
|
if (collection.internal) continue;
|
|
336
359
|
if (collection.name === "blog_post") continue;
|
|
337
360
|
try {
|
|
361
|
+
const defaultGrants = {
|
|
362
|
+
admin: ["read", "create", "update", "delete", "publish", "manage"],
|
|
363
|
+
editor: ["read", "create", "update", "publish"],
|
|
364
|
+
viewer: ["read"]
|
|
365
|
+
};
|
|
366
|
+
const baseGrants = collection.access ? { ...defaultGrants, ...collection.access } : defaultGrants;
|
|
338
367
|
await registry.register({
|
|
339
368
|
id: collection.name,
|
|
340
369
|
name: collection.name,
|
|
@@ -343,12 +372,7 @@ async function autoRegisterCollectionDocumentTypes(db) {
|
|
|
343
372
|
source: "system",
|
|
344
373
|
schema: anyObject,
|
|
345
374
|
settings: {
|
|
346
|
-
baseGrants
|
|
347
|
-
public: ["read"],
|
|
348
|
-
admin: ["read", "create", "update", "delete", "publish", "manage"],
|
|
349
|
-
editor: ["read", "create", "update", "publish"],
|
|
350
|
-
viewer: ["read"]
|
|
351
|
-
},
|
|
375
|
+
baseGrants,
|
|
352
376
|
maxVersionsPerRoot: 50,
|
|
353
377
|
...collection.versioning ? { versioning: true } : {}
|
|
354
378
|
},
|
|
@@ -363,6 +387,7 @@ async function autoRegisterCollectionDocumentTypes(db) {
|
|
|
363
387
|
}
|
|
364
388
|
|
|
365
389
|
// src/middleware/bootstrap.ts
|
|
390
|
+
chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
|
|
366
391
|
var bootstrapComplete = false;
|
|
367
392
|
function verifySecurityConfig(env) {
|
|
368
393
|
const warnings = [];
|
|
@@ -413,10 +438,14 @@ function bootstrapMiddleware(config = {}) {
|
|
|
413
438
|
if (path.startsWith("/images/") || path.startsWith("/assets/") || path === "/health" || path.endsWith(".js") || path.endsWith(".css") || path.endsWith(".png") || path.endsWith(".jpg") || path.endsWith(".ico")) {
|
|
414
439
|
return next();
|
|
415
440
|
}
|
|
441
|
+
const host = c.req.header("host") || "";
|
|
442
|
+
const isLocalhost = host.includes("localhost") || host.includes("127.0.0.1");
|
|
443
|
+
const gitBranch = c.env.GIT_BRANCH;
|
|
444
|
+
chunkK623Q6WD_cjs.setBranchLabel(isLocalhost && gitBranch ? gitBranch : void 0);
|
|
416
445
|
try {
|
|
417
446
|
console.log("[Bootstrap] Starting system initialization...");
|
|
418
447
|
console.log("[Bootstrap] Checking schema compatibility...");
|
|
419
|
-
const migrationService = new
|
|
448
|
+
const migrationService = new chunkTQG5FNNR_cjs.MigrationService(c.env.DB);
|
|
420
449
|
await migrationService.ensureSchemaCompatibility();
|
|
421
450
|
try {
|
|
422
451
|
const kv = c.env.CACHE_KV;
|
|
@@ -429,8 +458,8 @@ function bootstrapMiddleware(config = {}) {
|
|
|
429
458
|
}
|
|
430
459
|
console.log("[Bootstrap] Populating collection registry...");
|
|
431
460
|
try {
|
|
432
|
-
const configs = await
|
|
433
|
-
|
|
461
|
+
const configs = await chunk5ARIHAGN_cjs.loadCollectionConfigs();
|
|
462
|
+
chunk5ARIHAGN_cjs.getCollectionRegistry().register(configs);
|
|
434
463
|
console.log(`[Bootstrap] Registry populated with ${configs.length} collection(s)`);
|
|
435
464
|
} catch (error) {
|
|
436
465
|
console.error("[Bootstrap] Error populating collection registry:", error);
|
|
@@ -447,7 +476,7 @@ function bootstrapMiddleware(config = {}) {
|
|
|
447
476
|
console.error("[Bootstrap] Error repairing credential accounts:", error);
|
|
448
477
|
}
|
|
449
478
|
try {
|
|
450
|
-
const { RbacService: RbacService2 } = await import('./rbac-
|
|
479
|
+
const { RbacService: RbacService2 } = await import('./rbac-7QZ4JZ2E.cjs');
|
|
451
480
|
await new RbacService2(c.env.DB, c.env.CACHE_KV).ensureSystemRbacSeed();
|
|
452
481
|
} catch (error) {
|
|
453
482
|
console.error("[Bootstrap] Error seeding RBAC documents:", error);
|
|
@@ -460,7 +489,7 @@ function bootstrapMiddleware(config = {}) {
|
|
|
460
489
|
}
|
|
461
490
|
if (!config.plugins?.disableAll) {
|
|
462
491
|
console.log("[Bootstrap] Bootstrapping core plugins...");
|
|
463
|
-
const bootstrapService = new
|
|
492
|
+
const bootstrapService = new chunk5ARIHAGN_cjs.PluginBootstrapService(c.env.DB);
|
|
464
493
|
const needsBootstrap = await bootstrapService.isBootstrapNeeded();
|
|
465
494
|
if (needsBootstrap) {
|
|
466
495
|
await bootstrapService.bootstrapCorePlugins();
|
|
@@ -470,6 +499,52 @@ function bootstrapMiddleware(config = {}) {
|
|
|
470
499
|
}
|
|
471
500
|
bootstrapComplete = true;
|
|
472
501
|
console.log("[Bootstrap] System initialization completed");
|
|
502
|
+
try {
|
|
503
|
+
const registry = chunk5ARIHAGN_cjs.getCollectionRegistry();
|
|
504
|
+
const collections = registry.listActive();
|
|
505
|
+
const countResult = await c.env.DB.prepare(
|
|
506
|
+
`SELECT type_id, COUNT(*) AS cnt FROM documents
|
|
507
|
+
WHERE is_current_draft = 1 AND deleted_at IS NULL GROUP BY type_id`
|
|
508
|
+
).all();
|
|
509
|
+
const countMap = {};
|
|
510
|
+
let docTotal = 0;
|
|
511
|
+
for (const row of countResult.results ?? []) {
|
|
512
|
+
countMap[row.type_id] = row.cnt;
|
|
513
|
+
docTotal += row.cnt;
|
|
514
|
+
}
|
|
515
|
+
const fieldTypeHistogram = {};
|
|
516
|
+
for (const col of collections) {
|
|
517
|
+
const props = col.schema?.properties ?? {};
|
|
518
|
+
for (const field of Object.values(props)) {
|
|
519
|
+
const ft = field?.type ?? "unknown";
|
|
520
|
+
fieldTypeHistogram[ft] = (fieldTypeHistogram[ft] ?? 0) + 1;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
const activePlugins = (config.plugins?.register ?? []).map((p) => p.name ?? "unknown");
|
|
524
|
+
let installationId = "unknown";
|
|
525
|
+
try {
|
|
526
|
+
const kv = c.env.KV;
|
|
527
|
+
if (kv) {
|
|
528
|
+
installationId = await kv.get("_sonicjs_installation_id") ?? "";
|
|
529
|
+
if (!installationId) {
|
|
530
|
+
installationId = crypto.randomUUID();
|
|
531
|
+
await kv.put("_sonicjs_installation_id", installationId);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
} catch {
|
|
535
|
+
}
|
|
536
|
+
const telemetry = chunk5ARIHAGN_cjs.getTelemetryService();
|
|
537
|
+
await telemetry.trackProjectSnapshot({
|
|
538
|
+
installation_id: installationId,
|
|
539
|
+
collection_names: collections.map((c2) => c2.name),
|
|
540
|
+
collection_counts: countMap,
|
|
541
|
+
active_plugins: activePlugins,
|
|
542
|
+
field_type_histogram: fieldTypeHistogram,
|
|
543
|
+
doc_total: docTotal,
|
|
544
|
+
sonicjs_version: chunkAQJEMVAY_cjs.SONICJS_VERSION
|
|
545
|
+
});
|
|
546
|
+
} catch {
|
|
547
|
+
}
|
|
473
548
|
} catch (error) {
|
|
474
549
|
console.error("[Bootstrap] Error during system initialization:", error);
|
|
475
550
|
}
|
|
@@ -823,7 +898,7 @@ var requireRbac = (resource, verb) => {
|
|
|
823
898
|
if (cachedPerms !== void 0) {
|
|
824
899
|
allowed = cachedPerms.includes(`${resource}:${verb}`);
|
|
825
900
|
} else {
|
|
826
|
-
allowed = await new
|
|
901
|
+
allowed = await new chunkLTZ5WYOK_cjs.RbacService(c.env.DB).can(user.userId, resource, verb);
|
|
827
902
|
}
|
|
828
903
|
if (!allowed) {
|
|
829
904
|
const acceptHeader = c.req.header("Accept") || "";
|
|
@@ -1163,5 +1238,5 @@ exports.securityHeadersMiddleware = securityHeadersMiddleware;
|
|
|
1163
1238
|
exports.securityLoggingMiddleware = securityLoggingMiddleware;
|
|
1164
1239
|
exports.validateCsrfToken = validateCsrfToken;
|
|
1165
1240
|
exports.verifySecurityConfig = verifySecurityConfig;
|
|
1166
|
-
//# sourceMappingURL=chunk-
|
|
1167
|
-
//# sourceMappingURL=chunk-
|
|
1241
|
+
//# sourceMappingURL=chunk-4SHNHNRP.cjs.map
|
|
1242
|
+
//# sourceMappingURL=chunk-4SHNHNRP.cjs.map
|