@graph8/sdk 0.373.0 → 0.374.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. package/README.md +3 -3
  2. package/blocks/_foundation/README.md +47 -0
  3. package/blocks/_foundation/block.json +13 -0
  4. package/blocks/_foundation/components/auth-gate.tsx +363 -0
  5. package/blocks/_foundation/server/auth.ts +815 -0
  6. package/blocks/campaigns/README.md +1 -1
  7. package/blocks/campaigns/block.json +34 -1
  8. package/blocks/campaigns/components/campaign-links.tsx +180 -0
  9. package/blocks/company-intelligence/components/research-run.tsx +6 -2
  10. package/blocks/crm/README.md +19 -0
  11. package/blocks/crm/block.json +205 -6
  12. package/blocks/crm/components/bulk-update.tsx +119 -0
  13. package/blocks/crm/components/contact-documents-tab.tsx +144 -0
  14. package/blocks/crm/components/contact-insights-tab.tsx +118 -0
  15. package/blocks/crm/components/contact-lookup-link.tsx +47 -6
  16. package/blocks/crm/components/contact-row-actions.tsx +43 -0
  17. package/blocks/crm/components/contact-tag-chips.tsx +113 -0
  18. package/blocks/crm/components/contacts-screen.tsx +46 -5
  19. package/blocks/crm/components/owner-assign.tsx +132 -0
  20. package/blocks/crm/components/record-open-links.tsx +79 -0
  21. package/blocks/crm/components/tag-assign.tsx +112 -0
  22. package/blocks/crm/components/tag-manager.tsx +178 -0
  23. package/blocks/crm/components/unlock-info-button.tsx +82 -0
  24. package/blocks/crm/components/verify-email-button.tsx +93 -0
  25. package/blocks/crm/hooks/use-contact-tags.ts +29 -0
  26. package/blocks/crm/lib/record-actions.ts +102 -0
  27. package/blocks/deals/README.md +1 -0
  28. package/blocks/deals/block.json +17 -0
  29. package/blocks/deals/components/create-deal-button.tsx +109 -0
  30. package/blocks/deals/components/deal-detail.tsx +5 -3
  31. package/blocks/dialer/components/call-log-screen.tsx +6 -1
  32. package/blocks/documents/README.md +86 -0
  33. package/blocks/documents/block.json +378 -0
  34. package/blocks/documents/components/account-bar.tsx +48 -0
  35. package/blocks/documents/components/correspondence-form.tsx +95 -0
  36. package/blocks/documents/components/correspondence-import.tsx +106 -0
  37. package/blocks/documents/components/correspondence-panel.tsx +191 -0
  38. package/blocks/documents/components/documents-screen.tsx +76 -0
  39. package/blocks/documents/components/library-document-detail.tsx +175 -0
  40. package/blocks/documents/components/library-document-form.tsx +105 -0
  41. package/blocks/documents/components/library-folder-form.tsx +74 -0
  42. package/blocks/documents/components/library-panel.tsx +235 -0
  43. package/blocks/documents/components/library-upload.tsx +160 -0
  44. package/blocks/documents/components/question-row.tsx +130 -0
  45. package/blocks/documents/components/questionnaire-detail.tsx +197 -0
  46. package/blocks/documents/components/questionnaires-panel.tsx +173 -0
  47. package/blocks/documents/components/record-documents-tab.tsx +109 -0
  48. package/blocks/documents/lib/documents-types.ts +252 -0
  49. package/blocks/documents/lib/download.ts +64 -0
  50. package/blocks/documents/recipes/follow-a-questionnaire.ts +26 -0
  51. package/blocks/documents/recipes/log-account-correspondence.ts +27 -0
  52. package/blocks/documents/recipes/organize-the-library.ts +25 -0
  53. package/blocks/email-signatures/README.md +123 -0
  54. package/blocks/email-signatures/block.json +341 -0
  55. package/blocks/email-signatures/components/email-signatures-screen.tsx +166 -0
  56. package/blocks/email-signatures/components/signature-assign-template.tsx +119 -0
  57. package/blocks/email-signatures/components/signature-block-editor.tsx +87 -0
  58. package/blocks/email-signatures/components/signature-campaign-form.tsx +165 -0
  59. package/blocks/email-signatures/components/signature-campaigns.tsx +75 -0
  60. package/blocks/email-signatures/components/signature-identity-form.tsx +131 -0
  61. package/blocks/email-signatures/components/signature-mailboxes.tsx +195 -0
  62. package/blocks/email-signatures/components/signature-policy.tsx +130 -0
  63. package/blocks/email-signatures/components/signature-preview.tsx +119 -0
  64. package/blocks/email-signatures/components/signature-report.tsx +77 -0
  65. package/blocks/email-signatures/components/signature-template-details.tsx +112 -0
  66. package/blocks/email-signatures/components/signature-template-form.tsx +109 -0
  67. package/blocks/email-signatures/hooks/use-signatures-data.ts +93 -0
  68. package/blocks/email-signatures/lib/signatures-types.ts +392 -0
  69. package/blocks/email-signatures/recipes/assign-a-signature-to-a-new-hire.ts +32 -0
  70. package/blocks/email-signatures/recipes/create-a-template-and-make-it-default.ts +35 -0
  71. package/blocks/email-signatures/recipes/signature-engagement-report.ts +16 -0
  72. package/blocks/enrichment/README.md +22 -4
  73. package/blocks/enrichment/block.json +145 -5
  74. package/blocks/enrichment/components/auto-enrichment-configs.tsx +134 -0
  75. package/blocks/enrichment/components/auto-enrichment-settings.tsx +82 -0
  76. package/blocks/enrichment/components/bulk-enrich-panel.tsx +7 -7
  77. package/blocks/enrichment/components/enrichment-activity.tsx +93 -0
  78. package/blocks/enrichment/components/enrichment-job-detail.tsx +18 -0
  79. package/blocks/enrichment/components/enrichment-screen.tsx +34 -3
  80. package/blocks/enrichment/components/list-pipelines.tsx +97 -0
  81. package/blocks/enrichment/components/pipeline-detail.tsx +214 -0
  82. package/blocks/enrichment/components/pipeline-editor.tsx +144 -0
  83. package/blocks/enrichment/components/pipeline-templates.tsx +90 -0
  84. package/blocks/enrichment/lib/enrichment-types.ts +12 -0
  85. package/blocks/enrichment/lib/pipeline-types.ts +234 -0
  86. package/blocks/forms/README.md +2 -0
  87. package/blocks/forms/components/forms-screen.tsx +6 -3
  88. package/blocks/inbox/README.md +40 -4
  89. package/blocks/inbox/block.json +130 -8
  90. package/blocks/inbox/components/blocked-senders.tsx +103 -0
  91. package/blocks/inbox/components/compose-message.tsx +193 -0
  92. package/blocks/inbox/components/inbox-screen.tsx +54 -6
  93. package/blocks/inbox/components/inbox-search.tsx +106 -0
  94. package/blocks/inbox/components/tag-manager.tsx +136 -0
  95. package/blocks/inbox/components/thread-actions.tsx +133 -0
  96. package/blocks/inbox/components/thread-view.tsx +2 -0
  97. package/blocks/inbox/hooks/use-inbox-mailboxes.ts +31 -0
  98. package/blocks/inbox/lib/inbox-manage.ts +227 -0
  99. package/blocks/newsletter/components/newsletter-screen.tsx +3 -1
  100. package/blocks/pages/block.json +10 -1
  101. package/blocks/pages/hooks/use-landing-page-paths.ts +60 -0
  102. package/blocks/programmatic-pages/README.md +82 -0
  103. package/blocks/programmatic-pages/block.json +292 -0
  104. package/blocks/programmatic-pages/components/programmatic-campaign-form.tsx +136 -0
  105. package/blocks/programmatic-pages/components/programmatic-generate.tsx +112 -0
  106. package/blocks/programmatic-pages/components/programmatic-generated-pages.tsx +210 -0
  107. package/blocks/programmatic-pages/components/programmatic-overview.tsx +84 -0
  108. package/blocks/programmatic-pages/components/programmatic-pages-screen.tsx +221 -0
  109. package/blocks/programmatic-pages/components/programmatic-preview.tsx +66 -0
  110. package/blocks/programmatic-pages/components/programmatic-publish.tsx +102 -0
  111. package/blocks/programmatic-pages/components/programmatic-settings.tsx +96 -0
  112. package/blocks/programmatic-pages/components/programmatic-source-fields.tsx +75 -0
  113. package/blocks/programmatic-pages/components/programmatic-source.tsx +106 -0
  114. package/blocks/programmatic-pages/components/programmatic-variables.tsx +84 -0
  115. package/blocks/programmatic-pages/hooks/use-programmatic-workspace.ts +19 -0
  116. package/blocks/programmatic-pages/lib/programmatic-types.ts +330 -0
  117. package/blocks/programmatic-pages/recipes/create-a-programmatic-campaign.ts +23 -0
  118. package/blocks/programmatic-pages/recipes/render-and-follow.ts +21 -0
  119. package/blocks/programmatic-pages/recipes/review-then-publish.ts +17 -0
  120. package/blocks/quotes/README.md +25 -1
  121. package/blocks/quotes/block.json +123 -6
  122. package/blocks/quotes/components/manual-products.tsx +144 -0
  123. package/blocks/quotes/components/quote-batch-actions.tsx +86 -0
  124. package/blocks/quotes/components/quote-documents.tsx +94 -0
  125. package/blocks/quotes/components/quote-evidence.tsx +95 -0
  126. package/blocks/quotes/components/quote-list.tsx +23 -5
  127. package/blocks/quotes/components/quote-settings.tsx +184 -0
  128. package/blocks/quotes/components/quote-templates.tsx +189 -0
  129. package/blocks/quotes/components/quote-viewer.tsx +16 -3
  130. package/blocks/quotes/components/quotes-screen.tsx +15 -5
  131. package/blocks/quotes/lib/quote-admin.ts +264 -0
  132. package/blocks/sequencer/README.md +55 -0
  133. package/blocks/sequencer/block.json +172 -5
  134. package/blocks/sequencer/components/enrollment-withdraw.tsx +71 -0
  135. package/blocks/sequencer/components/sequence-builder.tsx +13 -3
  136. package/blocks/sequencer/components/sequence-campaign-link.tsx +78 -0
  137. package/blocks/sequencer/components/sequence-detail.tsx +6 -0
  138. package/blocks/sequencer/components/sequence-edit-form.tsx +111 -0
  139. package/blocks/sequencer/components/sequence-enrollments.tsx +2 -1
  140. package/blocks/sequencer/components/sequence-manage-actions.tsx +119 -0
  141. package/blocks/sequencer/components/sequence-senders-panel.tsx +84 -0
  142. package/blocks/sequencer/components/sequence-templates.tsx +160 -0
  143. package/blocks/sequencer/components/sequences-screen.tsx +36 -6
  144. package/blocks/sequencer/components/step-ai-assist.tsx +196 -0
  145. package/blocks/sequencer/components/step-editor.tsx +10 -1
  146. package/blocks/sequencer/components/step-templates.tsx +224 -0
  147. package/blocks/sequencer/lib/sequencer-manage.ts +235 -0
  148. package/blocks/sequencer/lib/sequencer-utils.ts +4 -0
  149. package/blocks/signals/README.md +39 -0
  150. package/blocks/signals/block.json +287 -0
  151. package/blocks/signals/components/auto-seed-panel.tsx +111 -0
  152. package/blocks/signals/components/listener-form.tsx +184 -0
  153. package/blocks/signals/components/matched-posts.tsx +195 -0
  154. package/blocks/signals/components/post-engagements.tsx +114 -0
  155. package/blocks/signals/components/record-social-tab.tsx +49 -0
  156. package/blocks/signals/components/social-listeners-screen.tsx +250 -0
  157. package/blocks/signals/components/social-settings.tsx +128 -0
  158. package/blocks/signals/components/source-lists.tsx +83 -0
  159. package/blocks/signals/components/top-engagers.tsx +68 -0
  160. package/blocks/signals/components/x-integration.tsx +129 -0
  161. package/blocks/signals/lib/signals-types.ts +228 -0
  162. package/blocks/signals/recipes/preview-and-create-a-listener.ts +16 -0
  163. package/blocks/signals/recipes/spend-against-caps.ts +14 -0
  164. package/blocks/signals/recipes/triage-matched-posts.ts +18 -0
  165. package/blocks/visitors/components/traffic-chart.tsx +3 -2
  166. package/blocks/web-analytics/README.md +102 -0
  167. package/blocks/web-analytics/block.json +292 -0
  168. package/blocks/web-analytics/components/acquisition-tab.tsx +154 -0
  169. package/blocks/web-analytics/components/analytics-filters.tsx +161 -0
  170. package/blocks/web-analytics/components/audience-tab.tsx +135 -0
  171. package/blocks/web-analytics/components/conversions-tab.tsx +128 -0
  172. package/blocks/web-analytics/components/engagement-tab.tsx +123 -0
  173. package/blocks/web-analytics/components/overview-tab.tsx +102 -0
  174. package/blocks/web-analytics/components/pages-tab.tsx +148 -0
  175. package/blocks/web-analytics/components/ranked-table.tsx +103 -0
  176. package/blocks/web-analytics/components/realtime-tab.tsx +103 -0
  177. package/blocks/web-analytics/components/report-card.tsx +71 -0
  178. package/blocks/web-analytics/components/web-analytics-screen.tsx +90 -0
  179. package/blocks/web-analytics/hooks/use-report.ts +48 -0
  180. package/blocks/web-analytics/lib/analytics-scope.ts +155 -0
  181. package/blocks/web-analytics/lib/page-path.ts +14 -0
  182. package/blocks/web-analytics/lib/web-analytics-types.ts +187 -0
  183. package/blocks/web-analytics/recipes/best-landing-pages.ts +26 -0
  184. package/blocks/web-analytics/recipes/form-conversion-check.ts +19 -0
  185. package/blocks/web-analytics/recipes/weekly-traffic-report.ts +37 -0
  186. package/blocks/workbench/README.md +54 -2
  187. package/blocks/workbench/block.json +234 -5
  188. package/blocks/workbench/components/workbench-auto-enrich.tsx +88 -0
  189. package/blocks/workbench/components/workbench-automation.tsx +36 -0
  190. package/blocks/workbench/components/workbench-connections.tsx +136 -0
  191. package/blocks/workbench/components/workbench-crm-import.tsx +91 -0
  192. package/blocks/workbench/components/workbench-datafile-import.tsx +154 -0
  193. package/blocks/workbench/components/workbench-grid.tsx +70 -7
  194. package/blocks/workbench/components/workbench-pipelines.tsx +173 -0
  195. package/blocks/workbench/components/workbench-row-actions.tsx +8 -1
  196. package/blocks/workbench/components/workbench-schedule.tsx +191 -0
  197. package/blocks/workbench/components/workbench-screen.tsx +50 -17
  198. package/blocks/workbench/components/workbench-send-to-sequence.tsx +116 -0
  199. package/blocks/workbench/components/workbench-table-settings.tsx +53 -0
  200. package/blocks/workbench/components/workbench-triggers.tsx +178 -0
  201. package/blocks/workbench/hooks/use-connected-crms.ts +29 -0
  202. package/blocks/workbench/lib/api-status.ts +8 -0
  203. package/blocks/workbench/lib/automation-types.ts +257 -0
  204. package/dist/cli.js +257 -51
  205. package/dist/index.browser.js +1 -1
  206. package/dist/index.browser.js.map +1 -1
  207. package/dist/index.browser.mjs +1 -1
  208. package/dist/index.browser.mjs.map +1 -1
  209. package/dist/index.js +1 -1
  210. package/dist/index.js.map +1 -1
  211. package/dist/index.mjs +1 -1
  212. package/dist/index.mjs.map +1 -1
  213. package/dist/react.browser.js +1 -1
  214. package/dist/react.browser.js.map +1 -1
  215. package/dist/react.browser.mjs +1 -1
  216. package/dist/react.browser.mjs.map +1 -1
  217. package/dist/react.js +1 -1
  218. package/dist/react.js.map +1 -1
  219. package/dist/react.mjs +1 -1
  220. package/dist/react.mjs.map +1 -1
  221. package/dist/types/blocks/auth.d.ts +45 -0
  222. package/dist/types/blocks/create.d.ts +5 -2
  223. package/dist/types/version.d.ts +2 -2
  224. package/docs/api/forms.md +1 -1
  225. package/package.json +1 -1
  226. package/stacks/6sense/pages/contacts.tsx.tmpl +2 -0
  227. package/stacks/6sense.json +20 -0
  228. package/stacks/apollo/pages/calls.tsx.tmpl +9 -9
  229. package/stacks/apollo/pages/campaigns.tsx.tmpl +27 -0
  230. package/stacks/apollo/pages/contacts.tsx.tmpl +6 -0
  231. package/stacks/apollo/pages/inbox-contact.tsx.tmpl +3 -3
  232. package/stacks/apollo/pages/lists.tsx.tmpl +14 -2
  233. package/stacks/apollo/pages/sequences.tsx.tmpl +8 -2
  234. package/stacks/apollo.json +33 -2
  235. package/stacks/clay/pages/contacts.tsx.tmpl +2 -0
  236. package/stacks/clay/pages/lists.tsx.tmpl +14 -2
  237. package/stacks/gong/pages/calls.tsx.tmpl +9 -9
  238. package/stacks/gong/pages/contacts.tsx.tmpl +2 -0
  239. package/stacks/hootsuite/pages/contacts.tsx.tmpl +2 -0
  240. package/stacks/hootsuite.json +10 -0
  241. package/stacks/hubspot/pages/campaigns.tsx.tmpl +30 -0
  242. package/stacks/hubspot/pages/companies.tsx.tmpl +2 -0
  243. package/stacks/hubspot/pages/contacts.tsx.tmpl +6 -0
  244. package/stacks/hubspot/pages/deals.tsx.tmpl +4 -0
  245. package/stacks/hubspot/pages/forms.tsx.tmpl +36 -0
  246. package/stacks/hubspot/pages/inbox.tsx.tmpl +2 -2
  247. package/stacks/hubspot/pages/sequences.tsx.tmpl +8 -2
  248. package/stacks/hubspot/pages/web-analytics.tsx.tmpl +14 -0
  249. package/stacks/hubspot.json +45 -2
  250. package/stacks/intercom/pages/inbox-contact.tsx.tmpl +3 -3
  251. package/stacks/intercom.json +10 -0
  252. package/stacks/mailchimp/pages/contacts.tsx.tmpl +2 -0
  253. package/stacks/mailchimp/pages/forms.tsx.tmpl +36 -0
  254. package/stacks/mailchimp.json +2 -1
  255. package/stacks/outreach/pages/calls.tsx.tmpl +9 -9
  256. package/stacks/outreach/pages/campaigns.tsx.tmpl +27 -0
  257. package/stacks/outreach/pages/contacts.tsx.tmpl +2 -0
  258. package/stacks/outreach/pages/inbox-contact.tsx.tmpl +3 -3
  259. package/stacks/outreach/pages/sequences.tsx.tmpl +8 -2
  260. package/stacks/outreach.json +13 -2
  261. package/stacks/pipedrive/pages/contacts.tsx.tmpl +2 -0
  262. package/stacks/pipedrive/pages/inbox.tsx.tmpl +2 -2
  263. package/stacks/pipedrive.json +10 -0
  264. package/stacks/salesforce/pages/companies.tsx.tmpl +2 -0
  265. package/stacks/salesforce/pages/contacts.tsx.tmpl +6 -0
  266. package/stacks/salesforce/pages/deals.tsx.tmpl +4 -0
  267. package/stacks/salesforce.json +10 -0
  268. package/stacks/zoominfo/pages/contacts.tsx.tmpl +4 -0
  269. package/stacks/zoominfo/pages/lists.tsx.tmpl +14 -2
  270. package/stacks/zoominfo.json +20 -0
  271. package/styles/styles.css +1 -1
  272. package/templates/auth/auth-route.ts.tmpl +16 -0
  273. package/templates/auth/g8.auth.anonymous.ts.tmpl +15 -0
  274. package/templates/auth/g8.auth.basic.ts.tmpl +17 -0
  275. package/templates/auth/g8.auth.jwt.ts.tmpl +23 -0
  276. package/templates/auth/g8.auth.password.ts.tmpl +18 -0
  277. package/templates/auth/g8.auth.session.ts.tmpl +23 -0
  278. package/templates/auth/middleware.ts.tmpl +14 -0
  279. package/templates/next-app/README.md.tmpl +5 -0
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @title Import an account's messages so running it twice does not duplicate them
3
+ * @when Bringing emails, LinkedIn messages or call notes in from another system. Partial success is normal: the status is 200
4
+ * even when rows failed, so read `imported`, `skipped` and `errors`. A row whose `external_id` is already stored is SKIPPED,
5
+ * so send one on every row. `correspondence_date` is when the message HAPPENED, not when you import it: generated documents
6
+ * read it as the relationship timeline. `channel` is email, linkedin or call_notes; `direction` is inbound or outbound.
7
+ */
8
+ import { g8 } from "@graph8/sdk";
9
+
10
+ g8.init({ apiKey: process.env.G8_API_KEY! });
11
+
12
+ const accountId = process.env.G8_COMPANY_ID!; // a company id from g8.api.companies.listCompanies
13
+
14
+ const result = await g8.api.documents.importAccountCorrespondence({
15
+ path: { account_id: accountId },
16
+ body: {
17
+ items: [
18
+ { channel: "email", direction: "inbound", subject: "Re: pricing", content: "Thanks for the call, sending the quote today.", correspondence_date: "2026-09-30T14:00:00Z", external_id: "msg-1001" },
19
+ { channel: "call_notes", direction: "outbound", content: "Walked through the security review.", correspondence_date: "2026-10-02T16:30:00Z", external_id: "call-2002" },
20
+ ],
21
+ },
22
+ });
23
+ const r = result.data as { imported?: number; skipped?: number; errors?: string[] };
24
+ console.log(`${r.imported ?? 0} imported, ${r.skipped ?? 0} skipped, ${(r.errors ?? []).length} failed`);
25
+
26
+ const recent = await g8.api.documents.listAccountCorrespondence({ path: { account_id: accountId }, query: { limit: 10 } });
27
+ console.log((recent.data.items ?? []).length, "messages on the account");
@@ -0,0 +1,25 @@
1
+ /**
2
+ * @title Create a Library folder and a text document in it, then list what the folder holds
3
+ * @when Seeding the Library from a script. The folder must exist before a document can land in it, and a folder name is
4
+ * letters, numbers, spaces, hyphens and underscores (at most 50), three levels deep at most. A text document is stored exactly
5
+ * as sent (no extraction). Nothing here reaches anyone. To add a FILE (PDF, Word ...) the API takes multipart, which this
6
+ * typed client does not send: post it with `fetch` and a `FormData` to /api/v1/library/documents/upload.
7
+ */
8
+ import { g8 } from "@graph8/sdk";
9
+
10
+ g8.init({ apiKey: process.env.G8_API_KEY! });
11
+
12
+ const folder = await g8.api.documents.createLibraryFolder({ body: { name: "Case studies 2026", parent_path: "Library" } });
13
+ const folderPath = String((folder.data as { full_path?: string }).full_path ?? "Library/Case studies 2026");
14
+
15
+ const doc = await g8.api.documents.createLibraryDocument({
16
+ body: {
17
+ folder_path: folderPath,
18
+ file_name: "acme-rollout.md",
19
+ display_name: "Acme rollout",
20
+ content: "Acme moved 400 seats in six weeks.",
21
+ },
22
+ });
23
+
24
+ const inFolder = await g8.api.documents.listLibraryDocuments({ query: { folder_path: folderPath } });
25
+ console.log(folderPath, (doc.data as { id?: string }).id, (inFolder.data.items ?? []).length);
@@ -0,0 +1,123 @@
1
+ # email-signatures
2
+
3
+ Managed email signatures: design **one signature for the team** and keep every mailbox on it. A *template* is the shared
4
+ design (blocks, layout, font, colour, with placeholders such as `{{member.name}}`). A *deployment* binds one mailbox to one
5
+ employee and a template, and the platform installs or applies it. A *policy* decides whether signatures are managed at all,
6
+ which template is the default, and whether employees may change the unlocked parts. A *campaign* adds a banner to signatures
7
+ for a time window. Changing what a mailbox sends is consequential, so every such action is confirmed with the real number of
8
+ mailboxes it touches.
9
+
10
+ ## Screens
11
+
12
+ `EmailSignaturesScreen` (`components/email-signatures-screen.tsx`) is the finished page: templates, mailboxes, campaigns,
13
+ policy and report.
14
+
15
+ ```tsx
16
+ import { EmailSignaturesScreen } from "@/g8/email-signatures/components/email-signatures-screen";
17
+ export default function Page() { return <EmailSignaturesScreen />; }
18
+ ```
19
+
20
+ Tabs (`?tab=`): **Templates**, **Mailboxes**, **Campaigns**, **Policy**, **Report**. Open a template (`?id=`) for Preview,
21
+ Edit, Use on mailboxes and Details; `&view=full` shows it as a full page.
22
+
23
+ Flows: see every template (the list is complete: the API does not page it); create one from blocks and placeholders with a
24
+ live preview; preview a stored template as a sample or as a real employee on a real mailbox (full, compact, with the campaign
25
+ banner, or plain text); edit it (the form opens only after the full record has loaded, and a stale save is refused with
26
+ "Load the newer version"); apply it to chosen mailboxes, a department or every mailbox; make it the organisation default;
27
+ archive it. On **Mailboxes**: assign an employee to a mailbox (with a setup check first), push, restore the old signature and
28
+ change what a mailbox sends, one by one or in bulk. **Campaigns**: create and edit banner campaigns, preview the banner, and
29
+ test which mailbox and recipients it would reach. **Policy**: off, managed or enforced, default and department templates.
30
+ **Report**: impressions and clicks by mailbox and campaign.
31
+
32
+ Parts you can mount alone: `SignatureTemplateForm`, `TemplatePreview` (and `SafeSignatureFrame`), `SignatureAssignTemplate`,
33
+ `SignatureTemplateDetails`, `SignatureMailboxes`, `SignatureIdentityForm`, `SignaturePolicy`, `SignatureCampaigns`,
34
+ `SignatureCampaignForm`, `SignatureReport`, `SignatureBlockEditor`.
35
+
36
+ ## Install
37
+
38
+ ```
39
+ npx @graph8/sdk add email-signatures
40
+ ```
41
+
42
+ Installs `foundation` and `mailboxes` first if missing. Everything lands under `g8/email-signatures/`. The block does not use the `pickers` block on purpose: its `MemberPicker` reports a
43
+ user id, while a signature is assigned to a *directory employee* (`listSignatureMembers`, a different id), and the mailbox
44
+ list is merged with each mailbox's signature status, which no generic picker knows.
45
+
46
+ ## Prerequisites (the human must do these)
47
+
48
+ | Where | What | How to verify |
49
+ |---|---|---|
50
+ | graph8 | Mailboxes connected (Google or Microsoft in the app, or the mailboxes block). A signature is bound to a mailbox. | `GET /api/v1/mailboxes` lists it. |
51
+ | graph8 | The people who sign are team members **with an email address**. An employee without one cannot be assigned. | `GET /api/v1/signatures/members` lists them. |
52
+ | The app | Installing a signature inside a Google account needs the Google Workspace integration with the signature permission, granted by a Workspace admin. A deployment stuck at `needs_admin_grant` is missing it. Without native installation the signature is applied when mail is sent from the platform. | A deployment leaves `needs_admin_grant`. |
53
+ | graph8 key | `signatures:read`, `signatures:write`, `signatures:delete` (archive). `campaigns:read` lists mailboxes. | `g8.api.me.describeCurrentKey()` |
54
+ | Your app | `allowedPrefixes` must include `signatures` and `mailboxes`. | The route file lists them. |
55
+
56
+ ## The flow, in order (IDs passed between steps)
57
+
58
+ 1. **Template**: `createSignatureTemplate({ data: { name, layout, blocks, primary_color, font, brand_source } })` -> **`template.id`** and `template.version`. Exactly one required, locked `identity` block; at most one optional `banner`; unique block ids; required blocks are locked.
59
+ 2. **Preview**: `previewSignatureTemplate({ data })` for a draft, `previewSavedSignatureTemplate(template.id, { mailbox_id, member_id })` for a stored one. Pass **both** `mailbox_id` and `member_id` to render with that employee's real details, neither for sample data. Reads only.
60
+ 3. **Policy**: `getSignatureSettings` -> **`version`** (the *policy* version). `setDefaultSignatureTemplate(template.id, { version })` makes the template the default (confirmed). `updateSignatureSettings({ version, data })` turns management off, on (`default`) or `enforced`; on needs a default template, enforced needs every active mailbox assigned.
61
+ 4. **Employee and mailbox**: `listSignatureMembers` -> **`member.id`**; the mailbox from `listMailboxes` -> **`mailbox.id`**; `listSignatureDeployments` -> the mailbox's **`revision`** (0 when it has no assignment).
62
+ 5. **Check**: `previewSignatureSetup({ mailbox_id, data })` is a dry run against the mail provider (account and send-as resolve).
63
+ 6. **Assign**: `assignSignatureIdentity({ mailbox_ids, expected_revisions: { [mailbox.id]: revision }, confirm_takeover: true, data: { member_id, account_subject, send_as_email, template_id? } })` behind a confirmation. `account_subject` must be the employee's own directory email and `send_as_email` the mailbox address.
64
+ 7. **Bulk**: `assignSignatureTemplate(template.id, { mailbox_ids } | { department } | { all_mailboxes: true })` (exactly one; every target already assigned), `pushSignatures({ mailbox_ids })`, `pushSignature(mailbox.id, { version: revision })`.
65
+ 8. **Change or undo**: `changeSignatureSource(mailbox.id, { version, source: "org" | "template" | "custom", template_id? })`; `restoreSignature(mailbox.id, { version })` puts back what the mailbox had before (refused while the policy is `enforced`; parked as `restore_conflict` if the signature was edited elsewhere since).
66
+ 9. **Campaign**: `createSignatureCampaign({ data })` (banner block, `starts_at` / `ends_at` timezone-aware, status `draft`, `scheduled` or `paused`); only a `scheduled` campaign inside its dates is added. `previewSignatureCampaign` renders it and, with a mailbox and recipients, says whether it would apply.
67
+ 10. **Read**: `getSignatureReport`.
68
+
69
+ ## Default decisions (do not ask the human unless marked)
70
+
71
+ | Decision | Default | Ask? |
72
+ |---|---|---|
73
+ | New template | Classic stacked, Arial, text colour `#222222`, brand kit colour and font, one required locked identity block (the API's own defaults) | no |
74
+ | Which mailboxes get a template | None: a person chooses the mailboxes, a department or everyone and confirms the count | **yes** |
75
+ | Policy mode | Left as it is | **yes** |
76
+ | Assigning an employee to a mailbox | Account = the employee's directory email, send-as = the mailbox address, after the person agrees to the takeover | **yes** |
77
+ | Stopping a campaign | Set it to Paused (there is no delete) | no |
78
+ | Removing a template | Archive it, after giving its mailboxes another template | no |
79
+ | After editing a template | Push the mailboxes that use it | no |
80
+
81
+ ## Operation coverage (24 signatures operations, all reachable from `EmailSignaturesScreen`)
82
+
83
+ | Operation | Where |
84
+ |---|---|
85
+ | `listSignatureTemplates`, `getSignatureTemplate` | template list; the edit form (full record) |
86
+ | `createSignatureTemplate`, `updateSignatureTemplate` | `SignatureTemplateForm` |
87
+ | `archiveSignatureTemplate` | `SignatureTemplateDetails` (destructive, confirmed; disabled while the template is in use) |
88
+ | `setDefaultSignatureTemplate` | `SignatureTemplateDetails` (confirmed, sized from the mailboxes that follow the default) |
89
+ | `assignSignatureTemplate` | `SignatureAssignTemplate` (confirmed, sized from the mailboxes the choice covers) |
90
+ | `previewSignatureTemplate`, `previewSavedSignatureTemplate` | `TemplatePreview` |
91
+ | `listSignatureMembers` | employee menus |
92
+ | `listSignatureDeployments` | `SignatureMailboxes` and every count in a confirmation |
93
+ | `assignSignatureIdentity`, `previewSignatureSetup` | `SignatureIdentityForm` (takeover confirmed; setup check first) |
94
+ | `pushSignature`, `pushSignatures`, `restoreSignature`, `changeSignatureSource` | `SignatureMailboxes` (each confirmed) |
95
+ | `getSignatureSettings`, `updateSignatureSettings` | `SignaturePolicy` (save confirmed) |
96
+ | `listSignatureCampaigns`, `createSignatureCampaign`, `updateSignatureCampaign`, `previewSignatureCampaign` | `SignatureCampaigns`, `SignatureCampaignForm` |
97
+ | `getSignatureReport` | `SignatureReport` |
98
+
99
+ No operation of the namespace is skipped. The block also reads `listMailboxes` (the mailboxes to assign). Previews and the setup check are POSTs, so the contract tiers them as `write`; they change nothing.
100
+
101
+ ## API gaps (what is asked for that the API does not have)
102
+
103
+ | Asked for | Reality | What the block does |
104
+ |---|---|---|
105
+ | A list of template variables | None. The renderer resolves a fixed set (`member.*`, `mailbox.*`, `company.*`, `brand.*`). | A built-in placeholder list that mirrors the renderer (`lib/signatures-types.ts`). `{{x\|fallback}}` is supported. |
106
+ | Delete a template or a campaign | Templates can only be archived (refused while in use); campaigns cannot be removed. | Archive with the reason it is blocked; pause a campaign. |
107
+ | Read one campaign | There is `list` only. | Edit seeds from the list row, which is the complete stored campaign, and refreshes the list after a save. |
108
+ | Paging and filters | The template, member, deployment and campaign lists take no paging parameters and return everything. `listMailboxes` takes `limit` up to 500 and no page. | The UI says "All N"; a mailbox read that comes back full says "Showing the first 500 mailboxes". |
109
+ | Mailboxes with no signature yet | `listSignatureDeployments` only lists mailboxes that already have a deployment. | Merged with `listMailboxes` (needs `campaigns:read`); without that scope only the assigned mailboxes show, with a note. |
110
+ | Upload a logo or photo | Multipart uploads are not in the developer API. | Images are referenced by address. |
111
+ | Pick audience lists for a campaign | The block has no list picker (it does not depend on the lists block). | A campaign that already targets lists keeps them on every save and can have the targeting removed; add lists through `createSignatureCampaign` / `updateSignatureCampaign` (`recipient_list_ids`). |
112
+ | Employee self-service (`/me`) | An API key has no seat or directory identity. | Out of scope. Employee overrides are carried over unchanged when an assignment is edited. |
113
+ | Choose the Workspace integration | The integrations used by signatures are not listed by the API. | An existing assignment's integration is carried over; a new one lets the API pick. |
114
+ | Click-tracking redirect | Public, unauthenticated by design. | Not an API capability. |
115
+ | Edit part of a template | `updateSignatureTemplate` and `updateSignatureSettings` replace the document. | The whole template is sent, built from the full record that was read; a cleared field is sent empty (`""`), a cleared default template as `null`; a save with no change sends nothing. |
116
+
117
+ ## Things that surprise people
118
+
119
+ - Every write carries the version or revision that was read. A concurrent change answers **409**; the screen says so and offers the newer version. The **policy** has its own version, used by set-default and the policy save.
120
+ - Signature HTML comes from the API and a template can carry custom markup, so the preview shows it in a **sandboxed frame** with no scripts. Never put signature HTML into your own page with `dangerouslySetInnerHTML`.
121
+ - A required block with a placeholder that has no fallback fails to render for an employee whose directory entry lacks that value. Add `{{member.title|Team}}`.
122
+ - Campaign targeting by audience list applies only to mail sent from a sequence. Dates are picked in the viewer's time zone and sent as timezone-aware instants.
123
+ - Enforced mode refuses a restore and employee changes; turning management **off** stops managing every mailbox.
@@ -0,0 +1,341 @@
1
+ {
2
+ "$schema": "../block.schema.json",
3
+ "id": "email-signatures",
4
+ "title": "Email signatures",
5
+ "summary": "Design one signature for the team and keep every mailbox on it: templates with a live preview, assignment to mailboxes and employees, the organisation default, banner campaigns, policy and engagement.",
6
+ "features": [
7
+ "signature templates built from blocks and placeholders, with a safe live preview as a sample or as a real employee",
8
+ "apply a template to chosen mailboxes, a department or everyone, confirmed with the real number of mailboxes",
9
+ "make a template the organisation default or archive it, both confirmed",
10
+ "assign an employee to a mailbox (setup check first), push, restore the old signature and change a mailbox's source",
11
+ "banner campaigns for a time window with targeting, a preview and a who-would-see-it test",
12
+ "policy: off, managed or enforced, default and department templates, employee overrides, cold-send variant",
13
+ "impressions and clicks by mailbox and campaign, with the limits of the numbers"
14
+ ],
15
+ "dependsOn": [
16
+ "mailboxes"
17
+ ],
18
+ "operations": [
19
+ "archive_signature_template_signatures_templates__template_id__delete",
20
+ "assign_signature_identity_signatures_assignments_post",
21
+ "assign_signature_template_signatures_templates__template_id__assign_post",
22
+ "change_signature_source_signatures_mailboxes__mailbox_id__source_post",
23
+ "create_signature_campaign_signatures_campaigns_post",
24
+ "create_signature_template_signatures_templates_post",
25
+ "get_signature_report_signatures_reports_get",
26
+ "get_signature_settings_signatures_settings_get",
27
+ "get_signature_template_signatures_templates__template_id__get",
28
+ "list_mailboxes_mailboxes_get",
29
+ "list_signature_campaigns_signatures_campaigns_get",
30
+ "list_signature_deployments_signatures_mailboxes_get",
31
+ "list_signature_members_signatures_members_get",
32
+ "list_signature_templates_signatures_templates_get",
33
+ "preview_saved_signature_template_signatures_templates__template_id__preview_post",
34
+ "preview_signature_campaign_signatures_campaigns_preview_post",
35
+ "preview_signature_setup_signatures_setup_preview_post",
36
+ "preview_signature_template_signatures_preview_post",
37
+ "push_signature_signatures_mailboxes__mailbox_id__push_post",
38
+ "push_signatures_signatures_mailboxes_push_post",
39
+ "restore_signature_signatures_mailboxes__mailbox_id__restore_post",
40
+ "set_default_signature_template_signatures_templates__template_id__set_default_post",
41
+ "update_signature_campaign_signatures_campaigns__campaign_id__patch",
42
+ "update_signature_settings_signatures_settings_put",
43
+ "update_signature_template_signatures_templates__template_id__patch"
44
+ ],
45
+ "components": [
46
+ {
47
+ "name": "EmailSignaturesScreen",
48
+ "file": "components/email-signatures-screen.tsx",
49
+ "purpose": "Finished email-signatures workspace: templates with a live preview, apply to mailboxes, the organisation default, mailboxes with push, restore and source, banner campaigns, the policy and the engagement report.",
50
+ "operations": [
51
+ "get_signature_settings_signatures_settings_get",
52
+ "list_signature_deployments_signatures_mailboxes_get",
53
+ "list_signature_templates_signatures_templates_get"
54
+ ],
55
+ "tiers": [
56
+ "read"
57
+ ]
58
+ },
59
+ {
60
+ "name": "SignatureTemplateForm",
61
+ "file": "components/signature-template-form.tsx",
62
+ "purpose": "Create or edit a signature template (layout, font, colour, blocks, placeholders) with a live preview; edit reads the full record first and a stale save is refused.",
63
+ "operations": [
64
+ "create_signature_template_signatures_templates_post",
65
+ "get_signature_template_signatures_templates__template_id__get",
66
+ "update_signature_template_signatures_templates__template_id__patch"
67
+ ],
68
+ "tiers": [
69
+ "read",
70
+ "write"
71
+ ]
72
+ },
73
+ {
74
+ "name": "SignatureBlockEditor",
75
+ "file": "components/signature-block-editor.tsx",
76
+ "purpose": "The ordered block list of a template: type, text, link, image, locked, required, placeholders, reorder and remove. A pure control that calls no operation.",
77
+ "operations": [],
78
+ "tiers": []
79
+ },
80
+ {
81
+ "name": "TemplatePreview",
82
+ "file": "components/signature-preview.tsx",
83
+ "purpose": "Render a draft or a stored template as a sample or as a real employee on a real mailbox, in full, compact or campaign form, or as plain text; the HTML is shown in a sandboxed frame (also exports SafeSignatureFrame).",
84
+ "operations": [
85
+ "list_mailboxes_mailboxes_get",
86
+ "list_signature_deployments_signatures_mailboxes_get",
87
+ "list_signature_members_signatures_members_get",
88
+ "preview_saved_signature_template_signatures_templates__template_id__preview_post",
89
+ "preview_signature_template_signatures_preview_post"
90
+ ],
91
+ "tiers": [
92
+ "read",
93
+ "write"
94
+ ]
95
+ },
96
+ {
97
+ "name": "SignatureAssignTemplate",
98
+ "file": "components/signature-assign-template.tsx",
99
+ "purpose": "Apply a template to chosen mailboxes, a department or every mailbox; confirmed with the number of mailboxes it really covers.",
100
+ "operations": [
101
+ "assign_signature_template_signatures_templates__template_id__assign_post",
102
+ "list_mailboxes_mailboxes_get",
103
+ "list_signature_deployments_signatures_mailboxes_get",
104
+ "list_signature_members_signatures_members_get"
105
+ ],
106
+ "tiers": [
107
+ "read",
108
+ "write"
109
+ ]
110
+ },
111
+ {
112
+ "name": "SignatureTemplateDetails",
113
+ "file": "components/signature-template-details.tsx",
114
+ "purpose": "One template's facts, make it the organisation default (confirmed, sized from the mailboxes that follow it) and archive it (confirmed; disabled while it is in use).",
115
+ "operations": [
116
+ "archive_signature_template_signatures_templates__template_id__delete",
117
+ "get_signature_settings_signatures_settings_get",
118
+ "list_signature_deployments_signatures_mailboxes_get",
119
+ "list_signature_members_signatures_members_get",
120
+ "set_default_signature_template_signatures_templates__template_id__set_default_post"
121
+ ],
122
+ "tiers": [
123
+ "read",
124
+ "write",
125
+ "destructive"
126
+ ]
127
+ },
128
+ {
129
+ "name": "SignatureMailboxes",
130
+ "file": "components/signature-mailboxes.tsx",
131
+ "purpose": "Every mailbox with its employee, template source and status; assign an employee, push (one or many), restore the old signature and change what a mailbox sends, each confirmed.",
132
+ "operations": [
133
+ "change_signature_source_signatures_mailboxes__mailbox_id__source_post",
134
+ "get_signature_settings_signatures_settings_get",
135
+ "list_mailboxes_mailboxes_get",
136
+ "list_signature_deployments_signatures_mailboxes_get",
137
+ "list_signature_members_signatures_members_get",
138
+ "list_signature_templates_signatures_templates_get",
139
+ "push_signature_signatures_mailboxes__mailbox_id__push_post",
140
+ "push_signatures_signatures_mailboxes_push_post",
141
+ "restore_signature_signatures_mailboxes__mailbox_id__restore_post"
142
+ ],
143
+ "tiers": [
144
+ "read",
145
+ "write"
146
+ ]
147
+ },
148
+ {
149
+ "name": "SignatureIdentityForm",
150
+ "file": "components/signature-identity-form.tsx",
151
+ "purpose": "Bind one mailbox to an employee: account and send-as derived from the choices, a dry-run setup check, then a confirmed takeover.",
152
+ "operations": [
153
+ "assign_signature_identity_signatures_assignments_post",
154
+ "list_signature_deployments_signatures_mailboxes_get",
155
+ "list_signature_members_signatures_members_get",
156
+ "list_signature_templates_signatures_templates_get",
157
+ "preview_signature_setup_signatures_setup_preview_post"
158
+ ],
159
+ "tiers": [
160
+ "read",
161
+ "write"
162
+ ]
163
+ },
164
+ {
165
+ "name": "SignaturePolicy",
166
+ "file": "components/signature-policy.tsx",
167
+ "purpose": "The organisation policy: off, managed or enforced, default and department templates, employee overrides, cold-send variant and native installation; a confirmed save of the changed fields.",
168
+ "operations": [
169
+ "get_signature_settings_signatures_settings_get",
170
+ "list_signature_deployments_signatures_mailboxes_get",
171
+ "list_signature_members_signatures_members_get",
172
+ "list_signature_templates_signatures_templates_get",
173
+ "update_signature_settings_signatures_settings_put"
174
+ ],
175
+ "tiers": [
176
+ "read",
177
+ "write"
178
+ ]
179
+ },
180
+ {
181
+ "name": "SignatureCampaigns",
182
+ "file": "components/signature-campaigns.tsx",
183
+ "purpose": "Banner campaigns with status, dates and priority; create and edit in a sheet.",
184
+ "operations": [
185
+ "list_signature_campaigns_signatures_campaigns_get"
186
+ ],
187
+ "tiers": [
188
+ "read"
189
+ ]
190
+ },
191
+ {
192
+ "name": "SignatureCampaignForm",
193
+ "file": "components/signature-campaign-form.tsx",
194
+ "purpose": "Create or edit a banner campaign (banner, dates, status, priority, who sees it), preview the banner and test which mailbox and recipients it would reach.",
195
+ "operations": [
196
+ "create_signature_campaign_signatures_campaigns_post",
197
+ "list_mailboxes_mailboxes_get",
198
+ "list_signature_deployments_signatures_mailboxes_get",
199
+ "list_signature_members_signatures_members_get",
200
+ "preview_signature_campaign_signatures_campaigns_preview_post",
201
+ "update_signature_campaign_signatures_campaigns__campaign_id__patch"
202
+ ],
203
+ "tiers": [
204
+ "read",
205
+ "write"
206
+ ]
207
+ },
208
+ {
209
+ "name": "SignatureReport",
210
+ "file": "components/signature-report.tsx",
211
+ "purpose": "Impressions and clicks by mailbox and campaign, with the limits the API states about the numbers.",
212
+ "operations": [
213
+ "get_signature_report_signatures_reports_get",
214
+ "list_mailboxes_mailboxes_get",
215
+ "list_signature_campaigns_signatures_campaigns_get",
216
+ "list_signature_deployments_signatures_mailboxes_get"
217
+ ],
218
+ "tiers": [
219
+ "read"
220
+ ]
221
+ }
222
+ ],
223
+ "hooks": [
224
+ {
225
+ "name": "useSignaturesData",
226
+ "file": "hooks/use-signatures-data.ts",
227
+ "purpose": "Shared cached reads: templates, one template, members, mailbox deployments, the policy, campaigns, and mailboxes merged with their deployments (the mailbox list is read once at the API's limit of 500 and says when it may be longer).",
228
+ "operations": [
229
+ "get_signature_settings_signatures_settings_get",
230
+ "get_signature_template_signatures_templates__template_id__get",
231
+ "list_mailboxes_mailboxes_get",
232
+ "list_signature_campaigns_signatures_campaigns_get",
233
+ "list_signature_deployments_signatures_mailboxes_get",
234
+ "list_signature_members_signatures_members_get",
235
+ "list_signature_templates_signatures_templates_get"
236
+ ]
237
+ }
238
+ ],
239
+ "lib": [
240
+ {
241
+ "file": "lib/signatures-types.ts",
242
+ "purpose": "Template, policy, deployment and campaign types; the API's exact vocabularies (block kinds, layouts, fonts, modes, statuses, sources); the placeholder list; template rules checked before a save; local-time helpers for campaign dates."
243
+ }
244
+ ],
245
+ "recipes": [
246
+ {
247
+ "file": "recipes/create-a-template-and-make-it-default.ts",
248
+ "title": "Create a signature template and make it the organisation default",
249
+ "when": "First-time setup; making it the default changes what mailboxes send, so a person confirms."
250
+ },
251
+ {
252
+ "file": "recipes/assign-a-signature-to-a-new-hire.ts",
253
+ "title": "Give a new hire's mailbox a managed signature",
254
+ "when": "Onboarding; a takeover of the mailbox's signature that a person agrees to."
255
+ },
256
+ {
257
+ "file": "recipes/signature-engagement-report.ts",
258
+ "title": "Report signature impressions and clicks",
259
+ "when": "A weekly digest or a dashboard backend."
260
+ }
261
+ ],
262
+ "prerequisites": [
263
+ {
264
+ "id": "mailboxes",
265
+ "description": "Mailboxes connected in the app (Google or Microsoft) or added through the mailboxes block. A signature is bound to a mailbox.",
266
+ "where": "api",
267
+ "verify": "GET /api/v1/mailboxes lists the mailbox."
268
+ },
269
+ {
270
+ "id": "directory-employees",
271
+ "description": "The people who sign must be team members with an email address in the directory. An employee without an email cannot be assigned.",
272
+ "where": "api",
273
+ "verify": "GET /api/v1/signatures/members lists them."
274
+ },
275
+ {
276
+ "id": "workspace-signature-access",
277
+ "description": "Installing a signature inside a Google account needs the Google Workspace integration with the signature permission granted by a Workspace admin in the app. A deployment that stops at needs_admin_grant is missing it. Without native installation the signature is applied when mail is sent from the platform.",
278
+ "where": "app",
279
+ "verify": "A deployment reaches an installed status instead of needs_admin_grant."
280
+ },
281
+ {
282
+ "id": "signature-scopes",
283
+ "description": "The key needs signatures:read, signatures:write and signatures:delete (archive). Listing mailboxes needs campaigns:read.",
284
+ "where": "api",
285
+ "verify": "g8.api.me.describeCurrentKey() lists the scopes."
286
+ },
287
+ {
288
+ "id": "proxy-allowlist",
289
+ "description": "Add \"signatures\" and \"mailboxes\" to allowedPrefixes in app/api/g8/[...path]/route.ts.",
290
+ "where": "app",
291
+ "verify": "The route file's allowedPrefixes contains them."
292
+ }
293
+ ],
294
+ "scopes": [
295
+ "campaigns:read",
296
+ "signatures:delete",
297
+ "signatures:read",
298
+ "signatures:write"
299
+ ],
300
+ "defaults": [
301
+ {
302
+ "decision": "New template",
303
+ "default": "Classic stacked layout, Arial, text colour #222222, brand kit colour and font, one required locked identity block with the employee's name and title",
304
+ "askHuman": false
305
+ },
306
+ {
307
+ "decision": "Which mailboxes get a template",
308
+ "default": "None: a person always chooses the mailboxes, a department or everyone, and confirms the count",
309
+ "askHuman": true
310
+ },
311
+ {
312
+ "decision": "Policy mode",
313
+ "default": "Leave it as it is; turning management on needs a default template, enforcing needs every active mailbox assigned",
314
+ "askHuman": true
315
+ },
316
+ {
317
+ "decision": "Assigning an employee to a mailbox",
318
+ "default": "Account = the employee's directory email, send-as = the mailbox address; only after a person agrees to the takeover",
319
+ "askHuman": true
320
+ },
321
+ {
322
+ "decision": "Stopping a campaign",
323
+ "default": "Set it to Paused (the API cannot delete a campaign)",
324
+ "askHuman": false
325
+ },
326
+ {
327
+ "decision": "Removing a template",
328
+ "default": "Archive it, after giving its mailboxes another template",
329
+ "askHuman": false
330
+ },
331
+ {
332
+ "decision": "After editing a template",
333
+ "default": "Push the mailboxes that use it from the Mailboxes tab",
334
+ "askHuman": false
335
+ }
336
+ ],
337
+ "peerDependencies": {
338
+ "react": ">=18",
339
+ "lucide-react": ">=0.400.0"
340
+ }
341
+ }