headroom-cms 0.1.8 → 0.1.10

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.
Files changed (123) hide show
  1. package/admin/assets/{AdminsPage-Bt_ekZen.js → AdminsPage-BIWASote.js} +1 -1
  2. package/admin/assets/AllContentPage-1gXe2OC7.js +1 -0
  3. package/admin/assets/{ApiKeysPage-BfWCxGhC.js → ApiKeysPage-BBW4ATBx.js} +1 -1
  4. package/admin/assets/AuditPage-B5GGFWGG.js +1 -0
  5. package/admin/assets/BlockEditor-CQpF8tYb.css +1 -0
  6. package/admin/assets/BlockEditor-ClskiZoX.js +176 -0
  7. package/admin/assets/BlockTypeEditPage-CY0gCPei.js +1 -0
  8. package/admin/assets/BlockTypesPage-D8Me6OeX.js +1 -0
  9. package/admin/assets/{BulkActionBar-TRiXXLQd.js → BulkActionBar--35xjnOP.js} +1 -1
  10. package/admin/assets/CollectionEditPage-y8t0ZO89.js +1 -0
  11. package/admin/assets/{CollectionsPage-ClplrxNn.js → CollectionsPage-BQmGXpvW.js} +1 -1
  12. package/admin/assets/{ContentCreatePage-DfYcEH1u.js → ContentCreatePage-DlgxamOe.js} +1 -1
  13. package/admin/assets/ContentEditPage-WkSbCnnG.js +1 -0
  14. package/admin/assets/ContentField-D04Uo1Ov.js +1 -0
  15. package/admin/assets/ContentListPage-BDMx7pWb.js +1 -0
  16. package/admin/assets/CustomBlockPreview-Cs9bFDh4.js +479 -0
  17. package/admin/assets/FieldRenderer-wE-mtqZB.js +2 -0
  18. package/admin/assets/FilterBar-kFcOLffg.js +1 -0
  19. package/admin/assets/FloatingComposerController-D4uLQfUX-C0Lhbmda.js +1 -0
  20. package/admin/assets/IconPicker-BrgSAsa_.js +3 -0
  21. package/admin/assets/{LoginPage-DutieANA.js → LoginPage-Bi7TBzK4.js} +1 -1
  22. package/admin/assets/MediaField-B-Cz8TlK.js +1 -0
  23. package/admin/assets/MediaPage-C84p9d1U.js +1 -0
  24. package/admin/assets/Pagination-CuHwUPHi.js +1 -0
  25. package/admin/assets/RelationshipPicker-Dv7GaLcU.js +1 -0
  26. package/admin/assets/{SiteSettingsPage-BtCC3RKc.js → SiteSettingsPage-nBT7NzkA.js} +1 -1
  27. package/admin/assets/{SiteUserEditPage-ClHmp0T-.js → SiteUserEditPage-DroUTii9.js} +1 -1
  28. package/admin/assets/SiteUsersPage-iVXPCBPe.js +1 -0
  29. package/admin/assets/{SitesPage-Bw_WBN6v.js → SitesPage-BefZeWuJ.js} +1 -1
  30. package/admin/assets/{SubmissionDetailPage-DS08LGxd.js → SubmissionDetailPage-ktmzzOE1.js} +1 -1
  31. package/admin/assets/SubmissionEditPage-C-ykTI2t.js +1 -0
  32. package/admin/assets/SubmissionListPage-DA-8deUy.js +1 -0
  33. package/admin/assets/{TagInput-BILCaC9b.js → TagInput-d-Hw1fkL.js} +1 -1
  34. package/admin/assets/{TagsPage-DdeZokow.js → TagsPage-BZzDvcKa.js} +1 -1
  35. package/admin/assets/{UsersPage-B0vLxjrg.js → UsersPage-CnQAOOGF.js} +1 -1
  36. package/admin/assets/{WebhookEditPage-SlJE4d3z.js → WebhookEditPage-KeS8hmdW.js} +1 -1
  37. package/admin/assets/{WebhooksPage-C6lGZLpr.js → WebhooksPage-CASjmlPN.js} +1 -1
  38. package/admin/assets/{card-hXVtlM0q.js → card-CZTHR2Qa.js} +1 -1
  39. package/admin/assets/checkbox-DEgzM8H9.js +1 -0
  40. package/admin/assets/{collapsible-B414SspL.js → collapsible-D3d29uJp.js} +1 -1
  41. package/admin/assets/{command-fvBFHye4.js → command-CdzYw11U.js} +1 -1
  42. package/admin/assets/contentStatus-CkPi9Dh6.js +1 -0
  43. package/admin/assets/{core.esm-B_kcYf6n.js → core.esm-DdQHdRkd.js} +2 -2
  44. package/admin/assets/index-BA3y7HJs.js +18 -0
  45. package/admin/assets/index-c7UygSvP.css +1 -0
  46. package/admin/assets/popover-BFw_h3j6.js +1 -0
  47. package/admin/assets/radix-C5ZmWuuL.js +51 -0
  48. package/admin/assets/select-dX9e6VDt.js +1 -0
  49. package/admin/assets/{serializeToText-DR_WnxiI.js → serializeToText-Zin3gYPm.js} +1 -1
  50. package/admin/assets/{sortable.esm-QyXA6fio.js → sortable.esm-qVEMoaTg.js} +1 -1
  51. package/admin/assets/{table-DLoIbCQ5.js → table-Dk7eeOt2.js} +1 -1
  52. package/admin/assets/{textarea-vSXNxwTe.js → textarea-CpDSUg2s.js} +1 -1
  53. package/admin/assets/useAdminResolver-Bljb4XGQ.js +1 -0
  54. package/admin/assets/useContent-CW0tm0FY.js +1 -0
  55. package/admin/assets/useContentSearch-_bwacEth.js +1 -0
  56. package/admin/assets/{useMedia-e3sqWm_t.js → useMedia-Cu5N4rY8.js} +1 -1
  57. package/admin/assets/usePageTitle-DYvuJQp6.js +1 -0
  58. package/admin/assets/useSiteUsers-CKtC_8Jc.js +1 -0
  59. package/admin/assets/{useTags-f7AVSLuj.js → useTags-ybsMbCst.js} +1 -1
  60. package/admin/assets/{useWebhooks-BH_r8-Mo.js → useWebhooks-BAB-3sLa.js} +1 -1
  61. package/admin/assets/yjs-tXBm_srz.js +5 -0
  62. package/admin/index.html +3 -3
  63. package/admin/sw.js +1 -1
  64. package/dist/admin-site.d.ts +12 -0
  65. package/dist/admin-site.d.ts.map +1 -1
  66. package/dist/admin-site.js +8 -1
  67. package/dist/admin-site.js.map +1 -1
  68. package/dist/api.d.ts +7 -0
  69. package/dist/api.d.ts.map +1 -1
  70. package/dist/api.js +8 -1
  71. package/dist/api.js.map +1 -1
  72. package/dist/collaboration.d.ts +55 -0
  73. package/dist/collaboration.d.ts.map +1 -0
  74. package/dist/collaboration.js +141 -0
  75. package/dist/collaboration.js.map +1 -0
  76. package/dist/index.d.ts +12 -0
  77. package/dist/index.d.ts.map +1 -1
  78. package/dist/index.js +29 -4
  79. package/dist/index.js.map +1 -1
  80. package/dist/storage.d.ts +2 -0
  81. package/dist/storage.d.ts.map +1 -1
  82. package/dist/storage.js +33 -0
  83. package/dist/storage.js.map +1 -1
  84. package/lambda/api/bootstrap +0 -0
  85. package/lambda/webhook-worker/bootstrap +0 -0
  86. package/package.json +1 -1
  87. package/src/admin-site.ts +20 -1
  88. package/src/api.ts +15 -1
  89. package/src/collaboration.ts +187 -0
  90. package/src/index.ts +44 -4
  91. package/src/sst-env.d.ts +28 -0
  92. package/src/storage.ts +35 -0
  93. package/admin/assets/AllContentPage-CFqEMAl9.js +0 -1
  94. package/admin/assets/AuditPage-BE0XIUl2.js +0 -1
  95. package/admin/assets/BlockEditor-6wqsThJ7.js +0 -179
  96. package/admin/assets/BlockEditor-Cp_wZ2xN.css +0 -1
  97. package/admin/assets/BlockTypeEditPage-CuNJfZw0.js +0 -1
  98. package/admin/assets/BlockTypesPage-BIMBVxBs.js +0 -1
  99. package/admin/assets/CollectionEditPage-BqX_0cC2.js +0 -1
  100. package/admin/assets/ContentEditPage-D3Rvlktk.js +0 -2
  101. package/admin/assets/ContentListPage-zmO8Is4d.js +0 -1
  102. package/admin/assets/CustomBlockPreview-C6HqS4xv.js +0 -479
  103. package/admin/assets/FieldBuilder-36tfpSyM.js +0 -3
  104. package/admin/assets/FilterBar-DhRwTqFv.js +0 -1
  105. package/admin/assets/MediaField-J2TLG_fu.js +0 -1
  106. package/admin/assets/MediaPage-DZZKMGF4.js +0 -1
  107. package/admin/assets/RelationshipPicker-CDFs4TMW.js +0 -1
  108. package/admin/assets/SiteUsersPage-AyJvcVM7.js +0 -1
  109. package/admin/assets/SubmissionEditPage-Brf-DK2X.js +0 -1
  110. package/admin/assets/SubmissionListPage-DNMzQZHS.js +0 -1
  111. package/admin/assets/checkbox-WGrS3sUr.js +0 -1
  112. package/admin/assets/contentStatus-BmaiYVOm.js +0 -1
  113. package/admin/assets/index-Cir9tY_P.js +0 -18
  114. package/admin/assets/index-DACBYsKM.css +0 -1
  115. package/admin/assets/popover-D5_HjjUC.js +0 -1
  116. package/admin/assets/radix-C1kb_NqW.js +0 -51
  117. package/admin/assets/select-_uJYxzeZ.js +0 -1
  118. package/admin/assets/useAdminResolver-D-LlmquD.js +0 -1
  119. package/admin/assets/useContent-e8beBIuq.js +0 -1
  120. package/admin/assets/useContentSearch-DOjveB9t.js +0 -1
  121. package/admin/assets/useDebouncedValue-C-cQUcLG.js +0 -1
  122. package/admin/assets/usePageTitle-BNSba9_L.js +0 -1
  123. package/admin/assets/useSiteUsers-BdnvuM2E.js +0 -1
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Collaboration Infrastructure
3
+ *
4
+ * API Gateway WebSocket API + DynamoDB Collab table + Node.js Lambda handler.
5
+ * Deployed at all times but dormant for solo editing — no Lambda invocations
6
+ * and no Collab table writes happen until collaboration is opted into.
7
+ *
8
+ * Supports dev mode (Node.js source with live reload) and package mode
9
+ * (pre-bundled handler).
10
+ *
11
+ * Split into two helpers:
12
+ * - `createCollabTable` — provisions just the DynamoDB Collab table.
13
+ * Must be called BEFORE `createApi`, because the Go API links the
14
+ * Collab table for ticket reads/writes.
15
+ * - `createCollabHandler` — provisions the WebSocket API + Lambda and
16
+ * wires `API_URL` into the Lambda environment so `snapshotToDraft`
17
+ * can `fetch` back into the Go API on `$disconnect`. Must be called
18
+ * AFTER `createApi`, because it needs `api.api.url`.
19
+ *
20
+ * The two halves are merged into a single `CollaborationResources` value
21
+ * by `index.ts` so downstream consumers (admin-site, etc.) see one shape.
22
+ */
23
+ import path from "path";
24
+ export function createCollabTable(name, _args = {}) {
25
+ // DynamoDB table for collaboration sessions + YJS state
26
+ const collabTable = new sst.aws.Dynamo(`${name}Collab`, {
27
+ fields: {
28
+ pk: "string",
29
+ sk: "string",
30
+ },
31
+ primaryIndex: { hashKey: "pk", rangeKey: "sk" },
32
+ // PascalCase to match the convention used throughout the collab TS
33
+ // package (RoomManager, YjsPersistence) and the Go ticket writer
34
+ // (repository/collab.go). DynamoDB attribute names are case-sensitive;
35
+ // the TTL attribute name must match what writers actually emit.
36
+ ttl: "ExpiresAt",
37
+ });
38
+ return { collabTable };
39
+ }
40
+ export function createCollabHandler(name, args) {
41
+ const { storage, auth, api, collabTable } = args;
42
+ // WebSocket API via raw Pulumi (SST v4 doesn't have a WebSocket component)
43
+ const wsApi = new aws.apigatewayv2.Api(`${name}WsApi`, {
44
+ protocolType: "WEBSOCKET",
45
+ routeSelectionExpression: "$request.body.action",
46
+ });
47
+ const handlerConfig = args.dev
48
+ ? {
49
+ handler: args.dev.handler,
50
+ runtime: "nodejs22.x",
51
+ }
52
+ : {
53
+ bundle: path.join(args.pkgRoot, "packages/collab"),
54
+ handler: "index.handler",
55
+ runtime: "nodejs22.x",
56
+ };
57
+ const wsHandler = new sst.aws.Function(`${name}CollabHandler`, {
58
+ ...handlerConfig,
59
+ // jsdom is pulled in transitively via @blocknote/server-util (used in
60
+ // src/yjs/converter.ts to convert YJS state to BlockNote blocks during
61
+ // the disconnect snapshot). esbuild does not auto-bundle jsdom's
62
+ // xhr-sync-worker.js because it's spawned dynamically at runtime
63
+ // (`new Worker(__dirname + "/xhr-sync-worker.js")`), so the worker file
64
+ // is missing on disk in the deployed Lambda and cold-starts fail with
65
+ // "Cannot find module './xhr-sync-worker.js'". Adding jsdom to
66
+ // `nodejs.install` excludes it from the esbuild bundle and instead
67
+ // installs it (with its full directory tree, including the worker file)
68
+ // into the function's node_modules/ at deploy time.
69
+ nodejs: {
70
+ install: ["jsdom"],
71
+ },
72
+ timeout: "30 seconds",
73
+ memory: "512 MB",
74
+ environment: {
75
+ COLLAB_TABLE: collabTable.name,
76
+ DRAFT_CONTENT_TABLE: storage.draftContent.name,
77
+ BLOCKS_TABLE: storage.blocks.name,
78
+ SITES_TABLE: storage.sites.name,
79
+ USER_POOL_ID: auth.userPool.id,
80
+ USER_POOL_CLIENT_ID: auth.userPoolClient.id,
81
+ WS_API_ENDPOINT: $interpolate `https://${wsApi.id}.execute-api.${aws.getRegionOutput().name}.amazonaws.com/${$app.stage}`,
82
+ // Required by `snapshotToDraft` (packages/collab/src/draft/snapshot.ts)
83
+ // which fetches `${apiUrl}/v1/admin/sites/{host}/content/{id}/draft`
84
+ // on `$disconnect` to persist the YJS room state back to DraftContent.
85
+ // Without this, the URL becomes `undefined/v1/admin/...` and the fetch
86
+ // throws "Failed to parse URL", crashing the disconnect Lambda.
87
+ API_URL: api.api.url,
88
+ // Shared with the Go API. Sent as `X-Headroom-Internal` on the
89
+ // disconnect snapshot PUT so the Go JWT middleware accepts the
90
+ // internal service-to-service call. See packages/api/internal/middleware/jwt.go.
91
+ INTERNAL_SECRET: storage.internalSecret.value,
92
+ // Phase 7.1 "Large documents": S3 bucket for YJS state that exceeds
93
+ // DynamoDB's 400KB per-item cap. See `YjsPersistence.saveState`.
94
+ COLLAB_STATE_BUCKET: storage.collabStateBucket.name,
95
+ },
96
+ link: [
97
+ collabTable,
98
+ storage.draftContent,
99
+ storage.blocks,
100
+ storage.sites,
101
+ storage.internalSecret,
102
+ // S3 link grants the Lambda IAM permissions for s3:GetObject /
103
+ // s3:PutObject on the bucket via SST's resource binding.
104
+ storage.collabStateBucket,
105
+ ],
106
+ permissions: [
107
+ {
108
+ actions: ["execute-api:ManageConnections"],
109
+ resources: [$interpolate `arn:aws:execute-api:*:*:${wsApi.id}/*`],
110
+ },
111
+ ],
112
+ });
113
+ // Wire up $connect, $default, $disconnect routes
114
+ const integration = new aws.apigatewayv2.Integration(`${name}WsIntegration`, {
115
+ apiId: wsApi.id,
116
+ integrationType: "AWS_PROXY",
117
+ integrationUri: wsHandler.nodes.function.invokeArn,
118
+ });
119
+ for (const routeKey of ["$connect", "$default", "$disconnect"]) {
120
+ new aws.apigatewayv2.Route(`${name}WsRoute${routeKey}`, {
121
+ apiId: wsApi.id,
122
+ routeKey,
123
+ target: $interpolate `integrations/${integration.id}`,
124
+ });
125
+ }
126
+ new aws.apigatewayv2.Stage(`${name}WsStage`, {
127
+ apiId: wsApi.id,
128
+ name: $app.stage,
129
+ autoDeploy: true,
130
+ });
131
+ // Grant API Gateway permission to invoke Lambda
132
+ new aws.lambda.Permission(`${name}WsPermission`, {
133
+ action: "lambda:InvokeFunction",
134
+ function: wsHandler.nodes.function.name,
135
+ principal: "apigateway.amazonaws.com",
136
+ sourceArn: $interpolate `${wsApi.executionArn}/*/*`,
137
+ });
138
+ const wsUrl = $interpolate `wss://${wsApi.id}.execute-api.${aws.getRegionOutput().name}.amazonaws.com/${$app.stage}`;
139
+ return { wsApi, wsHandler, wsUrl };
140
+ }
141
+ //# sourceMappingURL=collaboration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collaboration.js","sourceRoot":"","sources":["../src/collaboration.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -11,6 +11,7 @@ export type { ImageResources } from "./image.js";
11
11
  export type { ApiResources } from "./api.js";
12
12
  export type { CdnResources } from "./cdn.js";
13
13
  export type { SchedulerResources } from "./scheduler.js";
14
+ export type { CollaborationResources } from "./collaboration.js";
14
15
  export type { AdminSiteResources } from "./admin-site.js";
15
16
  export interface HeadroomCMSArgs {
16
17
  /**
@@ -74,7 +75,17 @@ export interface HeadroomCMSArgs {
74
75
  adminPath: string;
75
76
  /** Go source path for scheduler Lambda, e.g. "packages/scheduler" */
76
77
  schedulerHandler?: string;
78
+ /** SST handler for collab Lambda, e.g. "packages/collab/src/index.handler" */
79
+ collabHandler?: string;
77
80
  };
81
+ /**
82
+ * Build-time toggle for the collaboration feature in the admin UI.
83
+ * Defaults to `true`. Set `false` to keep the WebSocket / Collab table
84
+ * deployed but hide the "Collaborate" / "Request collaboration" buttons
85
+ * and refuse to open WebSockets — a kill-switch without teardown. Used
86
+ * to ship the feature to a stage before turning it on for editors.
87
+ */
88
+ collabEnabled?: boolean;
78
89
  }
79
90
  export declare class HeadroomCMS {
80
91
  readonly apiUrl: $util.Output<string>;
@@ -82,6 +93,7 @@ export declare class HeadroomCMS {
82
93
  readonly adminUrl: $util.Output<string>;
83
94
  readonly userPoolId: $util.Output<string>;
84
95
  readonly userPoolClientId: $util.Output<string>;
96
+ readonly collabWsUrl: $util.Output<string>;
85
97
  readonly outputs: Record<string, $util.Output<string>>;
86
98
  constructor(name: string, args: HeadroomCMSArgs);
87
99
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAwCH,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC/C,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,YAAY,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,MAAM,CAAC,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;QACb,gEAAgE;QAChE,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IAEF;;;OAGG;IACH,WAAW,CAAC,EAAE;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,gEAAgE;QAChE,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IAEF;;;OAGG;IACH,UAAU,CAAC,EAAE,gBAAgB,GAAG,gBAAgB,GAAG,gBAAgB,CAAC;IAEpE;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,cAAc,CAAC,EAAE;QACf,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAC3B,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAC3B,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,cAAc,CAAC,EAAE,OAAO,CAAC;KAC1B,CAAC;IAEF;;;OAGG;IACH,GAAG,CAAC,EAAE;QACJ,yDAAyD;QACzD,UAAU,EAAE,MAAM,CAAC;QACnB,wEAAwE;QACxE,oBAAoB,EAAE,MAAM,CAAC;QAC7B,gGAAgG;QAChG,oBAAoB,EAAE,MAAM,CAAC;QAC7B,+EAA+E;QAC/E,kBAAkB,EAAE,MAAM,CAAC;QAC3B,qDAAqD;QACrD,SAAS,EAAE,MAAM,CAAC;QAClB,qEAAqE;QACrE,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B,CAAC;CACH;AAED,qBAAa,WAAW;IACtB,SAAgB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC7C,SAAgB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC7C,SAAgB,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/C,SAAgB,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACjD,SAAgB,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAEvD,SAAgB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;gBAElD,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe;CAgGhD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAyCH,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC/C,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,YAAY,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,YAAY,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AACjE,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,MAAM,CAAC,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;QACb,gEAAgE;QAChE,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IAEF;;;OAGG;IACH,WAAW,CAAC,EAAE;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,gEAAgE;QAChE,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IAEF;;;OAGG;IACH,UAAU,CAAC,EAAE,gBAAgB,GAAG,gBAAgB,GAAG,gBAAgB,CAAC;IAEpE;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,cAAc,CAAC,EAAE;QACf,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAC3B,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAC3B,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,cAAc,CAAC,EAAE,OAAO,CAAC;KAC1B,CAAC;IAEF;;;OAGG;IACH,GAAG,CAAC,EAAE;QACJ,yDAAyD;QACzD,UAAU,EAAE,MAAM,CAAC;QACnB,wEAAwE;QACxE,oBAAoB,EAAE,MAAM,CAAC;QAC7B,gGAAgG;QAChG,oBAAoB,EAAE,MAAM,CAAC;QAC7B,+EAA+E;QAC/E,kBAAkB,EAAE,MAAM,CAAC;QAC3B,qDAAqD;QACrD,SAAS,EAAE,MAAM,CAAC;QAClB,qEAAqE;QACrE,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,8EAA8E;QAC9E,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;IAEF;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,qBAAa,WAAW;IACtB,SAAgB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC7C,SAAgB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC7C,SAAgB,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/C,SAAgB,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACjD,SAAgB,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACvD,SAAgB,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAElD,SAAgB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;gBAElD,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe;CA0HhD"}
package/dist/index.js CHANGED
@@ -13,6 +13,7 @@ import { createImage } from "./image.js";
13
13
  import { createApi } from "./api.js";
14
14
  import { createCdn } from "./cdn.js";
15
15
  import { createScheduler } from "./scheduler.js";
16
+ import { createCollabTable, createCollabHandler } from "./collaboration.js";
16
17
  import { createAdminSite } from "./admin-site.js";
17
18
  /**
18
19
  * Resolve the headroom-cms package root directory.
@@ -44,6 +45,7 @@ export class HeadroomCMS {
44
45
  adminUrl;
45
46
  userPoolId;
46
47
  userPoolClientId;
48
+ collabWsUrl;
47
49
  outputs;
48
50
  constructor(name, args) {
49
51
  // Only need pkgRoot for package mode (pre-built artifacts)
@@ -75,19 +77,38 @@ export class HeadroomCMS {
75
77
  ? { handler: args.dev.imageLambdaHandler }
76
78
  : undefined,
77
79
  });
78
- // 5. API Lambda (Go handler with access to all resources)
80
+ // 5a. Collaboration table (must exist before the API Lambda, which
81
+ // links it for ticket reads/writes).
82
+ const collabTable = createCollabTable(name);
83
+ // 6. API Lambda (Go handler with access to all resources)
79
84
  const api = createApi(name, {
80
85
  storage,
81
86
  auth,
82
87
  webhooks,
83
88
  image,
89
+ collab: collabTable,
84
90
  senderEmail: args.senderEmail,
85
91
  pkgRoot,
86
92
  dev: args.dev
87
93
  ? { handler: args.dev.apiHandler }
88
94
  : undefined,
89
95
  });
90
- // 6. Scheduler (EventBridge cron + Go Lambda + lock table)
96
+ // 5b. Collaboration WebSocket handler (must be created AFTER the API
97
+ // because its Lambda environment includes API_URL = api.api.url, which
98
+ // `snapshotToDraft` uses to PUT the disconnect snapshot back to the
99
+ // Go draft endpoint).
100
+ const collabHandler = createCollabHandler(name, {
101
+ storage,
102
+ auth,
103
+ api,
104
+ collabTable: collabTable.collabTable,
105
+ pkgRoot,
106
+ dev: args.dev?.collabHandler
107
+ ? { handler: args.dev.collabHandler }
108
+ : undefined,
109
+ });
110
+ const collab = { ...collabTable, ...collabHandler };
111
+ // 7. Scheduler (EventBridge cron + Go Lambda + lock table)
91
112
  const schedulerResources = createScheduler(name, {
92
113
  storage,
93
114
  api,
@@ -96,7 +117,7 @@ export class HeadroomCMS {
96
117
  ? { handler: args.dev.schedulerHandler }
97
118
  : undefined,
98
119
  });
99
- // 7. CDN (CloudFront distribution + edge functions)
120
+ // 8. CDN (CloudFront distribution + edge functions)
100
121
  const cdn = createCdn(name, {
101
122
  api,
102
123
  image,
@@ -106,16 +127,18 @@ export class HeadroomCMS {
106
127
  apiCacheTtl: args.apiCacheTtl,
107
128
  domain: args.domain,
108
129
  });
109
- // 8. Admin UI (static site)
130
+ // 9. Admin UI (static site)
110
131
  const admin = createAdminSite(name, {
111
132
  api,
112
133
  cdn,
113
134
  auth,
135
+ collab,
114
136
  pkgRoot,
115
137
  dev: args.dev
116
138
  ? { adminPath: args.dev.adminPath }
117
139
  : undefined,
118
140
  domain: args.adminDomain,
141
+ collabEnabled: args.collabEnabled,
119
142
  });
120
143
  // Expose outputs
121
144
  this.apiUrl = api.api.url;
@@ -123,12 +146,14 @@ export class HeadroomCMS {
123
146
  this.adminUrl = admin.url;
124
147
  this.userPoolId = auth.userPool.id;
125
148
  this.userPoolClientId = auth.userPoolClient.id;
149
+ this.collabWsUrl = collab.wsUrl;
126
150
  this.outputs = {
127
151
  api: api.api.url,
128
152
  cdn: cdn.url,
129
153
  admin: admin.url,
130
154
  userPoolId: auth.userPool.id,
131
155
  userPoolClientId: auth.userPoolClient.id,
156
+ collabWs: collab.wsUrl,
132
157
  };
133
158
  }
134
159
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/storage.d.ts CHANGED
@@ -16,7 +16,9 @@ export declare function createStorage(name: string): {
16
16
  relationships: sst.aws.Dynamo;
17
17
  siteUsers: sst.aws.Dynamo;
18
18
  contentBucket: sst.aws.Bucket;
19
+ collabStateBucket: sst.aws.Bucket;
19
20
  kvs: aws.cloudfront.KeyValueStore;
21
+ internalSecret: sst.Secret;
20
22
  };
21
23
  export type StorageResources = ReturnType<typeof createStorage>;
22
24
  //# sourceMappingURL=storage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM;;;;;;;;;;;;;EAiJzC;AAED,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC"}
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM;;;;;;;;;;;;;;;EAoLzC;AAED,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC"}
package/dist/storage.js CHANGED
@@ -119,10 +119,41 @@ export function createStorage(name) {
119
119
  },
120
120
  },
121
121
  });
122
+ // Phase 7.1 "Large documents": YJS room state that exceeds DynamoDB's 400KB
123
+ // per-item cap is uploaded here instead of being inlined on the Collab
124
+ // item. Dedicated bucket (vs reusing `contentBucket`) for two reasons:
125
+ // 1. `contentBucket` is `access: "cloudfront"` for media delivery; YJS
126
+ // state must NOT be CDN-fronted (it's per-collaboration-session
127
+ // transient state, never publicly addressable).
128
+ // 2. Lifecycle expiration is much shorter — these objects are recovery
129
+ // fallback for an active collaboration session; the matching Collab
130
+ // table item carries a 24h DynamoDB TTL, so the S3 lifecycle rule
131
+ // cleans up overflow objects on a similar timeline.
132
+ const collabStateBucket = new sst.aws.Bucket(`${name}CollabStateBucket`, {
133
+ transform: {
134
+ bucket: (args) => {
135
+ args.lifecycleRules = [
136
+ {
137
+ id: "expire-collab-state",
138
+ enabled: true,
139
+ expiration: { days: 7 },
140
+ // Keep the matching Collab DynamoDB TTL (24h) as the primary
141
+ // cleanup mechanism; this is a long-stop safety net so orphaned
142
+ // S3 objects don't accumulate forever.
143
+ },
144
+ ];
145
+ },
146
+ },
147
+ });
122
148
  const kvs = new aws.cloudfront.KeyValueStore(`${name}KVS`, {
123
149
  name: $interpolate `${$app.name}-${$app.stage}-kvs`,
124
150
  comment: "Headroom CMS edge data: API keys and site versions",
125
151
  });
152
+ // Shared secret for internal service-to-service auth between the collab
153
+ // Lambda and the Go API (`X-Headroom-Internal` header). Both Lambdas read
154
+ // this from their `INTERNAL_SECRET` environment variable. Set the value via
155
+ // `sst secret set HeadroomInternalSecret <value>` (or the namespaced equivalent).
156
+ const internalSecret = new sst.Secret(`${name}InternalSecret`);
126
157
  return {
127
158
  sites,
128
159
  content,
@@ -135,7 +166,9 @@ export function createStorage(name) {
135
166
  relationships,
136
167
  siteUsers,
137
168
  contentBucket,
169
+ collabStateBucket,
138
170
  kvs,
171
+ internalSecret,
139
172
  };
140
173
  }
141
174
  //# sourceMappingURL=storage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "headroom-cms",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "Headroom CMS — Serverless headless CMS for AWS, deployed with SST",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/admin-site.ts CHANGED
@@ -11,11 +11,13 @@ import path from "path";
11
11
  import type { ApiResources } from "./api.js";
12
12
  import type { CdnResources } from "./cdn.js";
13
13
  import type { AuthResources } from "./auth.js";
14
+ import type { CollaborationResources } from "./collaboration.js";
14
15
 
15
16
  export interface AdminSiteArgs {
16
17
  api: ApiResources;
17
18
  cdn: CdnResources;
18
19
  auth: AuthResources;
20
+ collab: CollaborationResources;
19
21
  pkgRoot: string;
20
22
  dev?: {
21
23
  /** Path to admin UI source, e.g. "packages/admin" */
@@ -25,10 +27,23 @@ export interface AdminSiteArgs {
25
27
  name: string;
26
28
  certificateArn: string;
27
29
  };
30
+ /**
31
+ * Build-time toggle for the entire collaboration UI. Defaults to `true`
32
+ * (collab is on whenever the WS infra is deployed). Set to `false` from
33
+ * the consuming SST config to keep the WebSocket / Collab DynamoDB table
34
+ * deployed but hide the "Collaborate" / "Request collaboration" buttons
35
+ * and refuse to open WebSockets — useful as a kill-switch without a full
36
+ * teardown. Plumbs to `VITE_COLLAB_ENABLED` in the admin Vite env; see
37
+ * `packages/admin/src/collab/featureFlag.ts` for the consumer.
38
+ */
39
+ collabEnabled?: boolean;
28
40
  }
29
41
 
30
42
  export function createAdminSite(name: string, args: AdminSiteArgs) {
31
- const { api, cdn, auth } = args;
43
+ const { api, cdn, auth, collab } = args;
44
+ // Default ON for backward compat — only emit "false" when explicitly
45
+ // disabled so existing stages without the flag set don't change behaviour.
46
+ const collabEnabledStr = args.collabEnabled === false ? "false" : "true";
32
47
 
33
48
  const domainConfig = args.domain
34
49
  ? {
@@ -54,6 +69,8 @@ export function createAdminSite(name: string, args: AdminSiteArgs) {
54
69
  VITE_USER_POOL_ID: auth.userPool.id,
55
70
  VITE_USER_POOL_CLIENT_ID: auth.userPoolClient.id,
56
71
  VITE_AWS_REGION: aws.getRegionOutput().name,
72
+ VITE_COLLAB_WS_URL: collab.wsUrl,
73
+ VITE_COLLAB_ENABLED: collabEnabledStr,
57
74
  },
58
75
  domain: domainConfig,
59
76
  });
@@ -84,6 +101,8 @@ export function createAdminSite(name: string, args: AdminSiteArgs) {
84
101
  '__HEADROOM_USER_POOL_ID__': '${auth.userPool.id}',
85
102
  '__HEADROOM_USER_POOL_CLIENT_ID__': '${auth.userPoolClient.id}',
86
103
  '__HEADROOM_AWS_REGION__': '${aws.getRegionOutput().name}',
104
+ '__HEADROOM_COLLAB_WS_URL__': '${collab.wsUrl}',
105
+ '__HEADROOM_COLLAB_ENABLED__': '${collabEnabledStr}',
87
106
  };
88
107
  function walk(d) {
89
108
  for (const f of fs.readdirSync(d)) {
package/src/api.ts CHANGED
@@ -10,12 +10,19 @@ import type { StorageResources } from "./storage.js";
10
10
  import type { AuthResources } from "./auth.js";
11
11
  import type { WebhookResources } from "./webhooks.js";
12
12
  import type { ImageResources } from "./image.js";
13
+ import type { CollabTableResources } from "./collaboration.js";
13
14
 
14
15
  export interface ApiArgs {
15
16
  storage: StorageResources;
16
17
  auth: AuthResources;
17
18
  webhooks: WebhookResources;
18
19
  image: ImageResources;
20
+ /**
21
+ * Just the collab DynamoDB table — the API Lambda only links the table
22
+ * for ticket reads/writes, it does NOT depend on the WebSocket handler.
23
+ * (The WS handler is created AFTER the API because its env needs api.url.)
24
+ */
25
+ collab: CollabTableResources;
19
26
  senderEmail: string;
20
27
  pkgRoot: string;
21
28
  dev?: {
@@ -25,7 +32,7 @@ export interface ApiArgs {
25
32
  }
26
33
 
27
34
  export function createApi(name: string, args: ApiArgs) {
28
- const { storage, auth, webhooks, image } = args;
35
+ const { storage, auth, webhooks, image, collab } = args;
29
36
 
30
37
  const handlerConfig = args.dev
31
38
  ? {
@@ -67,6 +74,11 @@ export function createApi(name: string, args: ApiArgs) {
67
74
  RELATIONSHIPS_TABLE: storage.relationships.name,
68
75
  SITE_USERS_TABLE: storage.siteUsers.name,
69
76
  SES_FROM_EMAIL: args.senderEmail,
77
+ COLLAB_TABLE: collab.collabTable.name,
78
+ // Shared with the collab Lambda. The Go JWT middleware verifies
79
+ // `X-Headroom-Internal` against this on internal service calls
80
+ // (collab → draft snapshot). See packages/api/internal/middleware/jwt.go.
81
+ INTERNAL_SECRET: storage.internalSecret.value,
70
82
  },
71
83
  link: [
72
84
  storage.sites,
@@ -84,6 +96,8 @@ export function createApi(name: string, args: ApiArgs) {
84
96
  image.imageSigningSecret,
85
97
  storage.relationships,
86
98
  storage.siteUsers,
99
+ collab.collabTable,
100
+ storage.internalSecret,
87
101
  ],
88
102
  permissions: [
89
103
  {