@anchrd/intel 0.59.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +496 -0
- package/bin/intel.mjs +134 -0
- package/dist/adapters/cloudflare/cloudflare-flow-workflow.d.ts +42 -0
- package/dist/adapters/cloudflare/cloudflare-flow-workflow.js +89 -0
- package/dist/adapters/cloudflare/cloudflare.d.ts +29 -0
- package/dist/adapters/cloudflare/cloudflare.js +416 -0
- package/dist/adapters/cloudflare/cloudflare.types.d.ts +31 -0
- package/dist/adapters/cloudflare/cloudflare.types.js +1 -0
- package/dist/adapters/content/content.d.ts +3 -0
- package/dist/adapters/content/content.js +128 -0
- package/dist/adapters/content/content.types.d.ts +38 -0
- package/dist/adapters/content/content.types.js +1 -0
- package/dist/adapters/db/db-audit.d.ts +62 -0
- package/dist/adapters/db/db-audit.js +150 -0
- package/dist/adapters/db/db-boards.d.ts +6 -0
- package/dist/adapters/db/db-boards.js +324 -0
- package/dist/adapters/db/db-feed.d.ts +30 -0
- package/dist/adapters/db/db-feed.js +276 -0
- package/dist/adapters/db/db-flows.d.ts +42 -0
- package/dist/adapters/db/db-flows.js +1311 -0
- package/dist/adapters/db/db-grants.d.ts +133 -0
- package/dist/adapters/db/db-grants.js +269 -0
- package/dist/adapters/db/db-indexing.d.ts +3 -0
- package/dist/adapters/db/db-indexing.js +200 -0
- package/dist/adapters/db/db-oauth.d.ts +3 -0
- package/dist/adapters/db/db-oauth.js +26 -0
- package/dist/adapters/db/db-prompts.d.ts +46 -0
- package/dist/adapters/db/db-prompts.js +144 -0
- package/dist/adapters/db/db.d.ts +6 -0
- package/dist/adapters/db/db.js +1687 -0
- package/dist/adapters/db/db.types.d.ts +16 -0
- package/dist/adapters/db/db.types.js +1 -0
- package/dist/adapters/document-converter/document-converter.d.ts +2 -0
- package/dist/adapters/document-converter/document-converter.js +26 -0
- package/dist/adapters/document-converter/document-converter.types.d.ts +17 -0
- package/dist/adapters/document-converter/document-converter.types.js +1 -0
- package/dist/adapters/flow-runtime/flow-runtime.d.ts +3 -0
- package/dist/adapters/flow-runtime/flow-runtime.js +22 -0
- package/dist/adapters/flow-runtime/flow-runtime.types.d.ts +19 -0
- package/dist/adapters/flow-runtime/flow-runtime.types.js +1 -0
- package/dist/adapters/index-queue/index-queue.d.ts +10 -0
- package/dist/adapters/index-queue/index-queue.js +12 -0
- package/dist/adapters/index-queue/index-queue.types.d.ts +11 -0
- package/dist/adapters/index-queue/index-queue.types.js +1 -0
- package/dist/adapters/json-schema/json-schema.d.ts +2 -0
- package/dist/adapters/json-schema/json-schema.js +77 -0
- package/dist/adapters/openid/openid.d.ts +5 -0
- package/dist/adapters/openid/openid.js +301 -0
- package/dist/adapters/portal-tokens/portal-tokens.d.ts +8 -0
- package/dist/adapters/portal-tokens/portal-tokens.js +79 -0
- package/dist/adapters/remote-tools/remote-tools.d.ts +5 -0
- package/dist/adapters/remote-tools/remote-tools.js +129 -0
- package/dist/adapters/semantic-index/semantic-index.d.ts +2 -0
- package/dist/adapters/semantic-index/semantic-index.js +139 -0
- package/dist/adapters/semantic-index/semantic-index.types.d.ts +56 -0
- package/dist/adapters/semantic-index/semantic-index.types.js +1 -0
- package/dist/adapters/session-cookie/session-cookie.d.ts +5 -0
- package/dist/adapters/session-cookie/session-cookie.js +87 -0
- package/dist/adapters/tool-source-policy/tool-source-policy.d.ts +1 -0
- package/dist/adapters/tool-source-policy/tool-source-policy.js +22 -0
- package/dist/audit/audit.d.ts +2 -0
- package/dist/audit/audit.js +87 -0
- package/dist/audit/audit.types.d.ts +23 -0
- package/dist/audit/audit.types.js +1 -0
- package/dist/auth/auth.d.ts +2 -0
- package/dist/auth/auth.js +284 -0
- package/dist/auth/auth.types.d.ts +108 -0
- package/dist/auth/auth.types.js +1 -0
- package/dist/boards/boards.d.ts +44 -0
- package/dist/boards/boards.js +447 -0
- package/dist/boards/boards.types.d.ts +117 -0
- package/dist/boards/boards.types.js +1 -0
- package/dist/build/build.d.ts +2 -0
- package/dist/build/build.js +192 -0
- package/dist/build/build.types.d.ts +17 -0
- package/dist/build/build.types.js +1 -0
- package/dist/bundle/bundle.d.ts +4 -0
- package/dist/bundle/bundle.js +1194 -0
- package/dist/bundle/bundle.types.d.ts +33 -0
- package/dist/bundle/bundle.types.js +1 -0
- package/dist/cli/cli.d.ts +4 -0
- package/dist/cli/cli.js +262 -0
- package/dist/cli/cli.types.d.ts +14 -0
- package/dist/cli/cli.types.js +1 -0
- package/dist/contract/audit.d.ts +50 -0
- package/dist/contract/audit.js +72 -0
- package/dist/contract/board.d.ts +150 -0
- package/dist/contract/board.js +262 -0
- package/dist/contract/bundle.d.ts +147 -0
- package/dist/contract/bundle.js +139 -0
- package/dist/contract/contract.d.ts +112 -0
- package/dist/contract/contract.js +143 -0
- package/dist/contract/feed.d.ts +126 -0
- package/dist/contract/feed.js +149 -0
- package/dist/contract/flow-run.d.ts +346 -0
- package/dist/contract/flow-run.js +194 -0
- package/dist/contract/flow.d.ts +1057 -0
- package/dist/contract/flow.js +552 -0
- package/dist/contract/node.d.ts +551 -0
- package/dist/contract/node.js +456 -0
- package/dist/contract/share.d.ts +216 -0
- package/dist/contract/share.js +134 -0
- package/dist/contract/table.d.ts +171 -0
- package/dist/contract/table.js +117 -0
- package/dist/contract/tool.d.ts +122 -0
- package/dist/contract/tool.js +172 -0
- package/dist/feed/feed.d.ts +2 -0
- package/dist/feed/feed.js +77 -0
- package/dist/feed/feed.types.d.ts +23 -0
- package/dist/feed/feed.types.js +1 -0
- package/dist/flows/flows.d.ts +41 -0
- package/dist/flows/flows.js +2216 -0
- package/dist/flows/flows.types.d.ts +339 -0
- package/dist/flows/flows.types.js +1 -0
- package/dist/http/http.d.ts +9 -0
- package/dist/http/http.js +874 -0
- package/dist/http/http.types.d.ts +22 -0
- package/dist/http/http.types.js +1 -0
- package/dist/indexing/indexing.d.ts +6 -0
- package/dist/indexing/indexing.js +239 -0
- package/dist/indexing/indexing.types.d.ts +11 -0
- package/dist/indexing/indexing.types.js +1 -0
- package/dist/intel/intel.d.ts +3 -0
- package/dist/intel/intel.js +194 -0
- package/dist/intel/intel.types.d.ts +24 -0
- package/dist/intel/intel.types.js +1 -0
- package/dist/mcp/mcp.d.ts +2 -0
- package/dist/mcp/mcp.js +1292 -0
- package/dist/mcp/mcp.types.d.ts +25 -0
- package/dist/mcp/mcp.types.js +1 -0
- package/dist/nodes/document-links/document-links.d.ts +20 -0
- package/dist/nodes/document-links/document-links.js +57 -0
- package/dist/nodes/nodes.d.ts +2 -0
- package/dist/nodes/nodes.js +1667 -0
- package/dist/nodes/nodes.types.d.ts +511 -0
- package/dist/nodes/nodes.types.js +1 -0
- package/dist/prepare/prepare.d.ts +4 -0
- package/dist/prepare/prepare.js +16 -0
- package/dist/prepare/prepare.types.d.ts +9 -0
- package/dist/prepare/prepare.types.js +1 -0
- package/dist/prompts/prompts.d.ts +2 -0
- package/dist/prompts/prompts.js +65 -0
- package/dist/prompts/prompts.types.d.ts +71 -0
- package/dist/prompts/prompts.types.js +1 -0
- package/dist/shared/callers/callers.d.ts +28 -0
- package/dist/shared/callers/callers.js +30 -0
- package/dist/shared/csv/csv.d.ts +13 -0
- package/dist/shared/csv/csv.js +85 -0
- package/dist/shared/document-text/document-text.d.ts +21 -0
- package/dist/shared/document-text/document-text.js +31 -0
- package/dist/shared/gate-authorization/gate-authorization.d.ts +5 -0
- package/dist/shared/gate-authorization/gate-authorization.js +26 -0
- package/dist/shared/grant-expiry/grant-expiry.d.ts +19 -0
- package/dist/shared/grant-expiry/grant-expiry.js +26 -0
- package/dist/shared/intel-error/intel-error.d.ts +22 -0
- package/dist/shared/intel-error/intel-error.js +27 -0
- package/dist/shared/plain-title/plain-title.d.ts +16 -0
- package/dist/shared/plain-title/plain-title.js +45 -0
- package/dist/shared/problem-details/problem-details.d.ts +30 -0
- package/dist/shared/problem-details/problem-details.js +18 -0
- package/dist/shared/report-unexpected-error/report-unexpected-error.d.ts +1 -0
- package/dist/shared/report-unexpected-error/report-unexpected-error.js +37 -0
- package/dist/shared/safe-return-path/safe-return-path.d.ts +2 -0
- package/dist/shared/safe-return-path/safe-return-path.js +11 -0
- package/dist/shared/sha256/sha256.d.ts +2 -0
- package/dist/shared/sha256/sha256.js +14 -0
- package/dist/tools/tool-servers/tool-servers.d.ts +46 -0
- package/dist/tools/tool-servers/tool-servers.js +177 -0
- package/dist/tools/tools.d.ts +2 -0
- package/dist/tools/tools.js +207 -0
- package/dist/tools/tools.types.d.ts +56 -0
- package/dist/tools/tools.types.js +1 -0
- package/examples/branding/favicon.svg +5 -0
- package/examples/branding/logo.svg +5 -0
- package/examples/branding/theme.css +16 -0
- package/examples/dev.vars.example +7 -0
- package/examples/intel.json +9 -0
- package/migrations/0000_intel_foundation.sql +203 -0
- package/migrations/0001_portal_native_tools.sql +21 -0
- package/migrations/0002_flows_in_the_knowledge_tree.sql +34 -0
- package/migrations/0003_folder_permissions.sql +211 -0
- package/migrations/0004_subflow_runs.sql +14 -0
- package/migrations/0005_flow_node_cleanup.sql +28 -0
- package/migrations/0005_tables_in_the_knowledge_tree.sql +68 -0
- package/migrations/0006_links_are_written_in_the_text.sql +20 -0
- package/migrations/0007_no_node_waits.sql +69 -0
- package/migrations/0008_three_layers.sql +130 -0
- package/migrations/0009_no_context_policy.sql +48 -0
- package/migrations/0010_no_run_waits_a_year.sql +27 -0
- package/migrations/0011_one_name_for_the_tree.sql +53 -0
- package/migrations/0012_table_snapshots.sql +29 -0
- package/migrations/0017_a_vector_per_card.sql +38 -0
- package/migrations/0018_no_context_policy_at_last.sql +97 -0
- package/migrations/0019_one_name_for_the_grants.sql +52 -0
- package/migrations/0020_cascade_purge_replay.sql +11 -0
- package/migrations/0021_a_flow_carries_its_own_grant.sql +44 -0
- package/migrations/0022_a_cursor_over_the_journal.sql +14 -0
- package/migrations/0023_a_board_and_its_tasks.sql +116 -0
- package/migrations/0024_the_archive_is_a_column.sql +33 -0
- package/migrations/0025_archiving_takes_the_subtree.sql +29 -0
- package/migrations/0026_one_feed_over_two_kinds.sql +23 -0
- package/migrations/0027_the_runs_of_every_flow.sql +27 -0
- package/migrations/0028_a_prompt_name_over_two_kinds.sql +70 -0
- package/package.json +118 -0
- package/src/contract/CLAUDE.md +152 -0
- package/src/contract/README.md +102 -0
- package/src/contract/audit.ts +85 -0
- package/src/contract/board.ts +306 -0
- package/src/contract/bundle.ts +157 -0
- package/src/contract/contract.ts +161 -0
- package/src/contract/feed.ts +165 -0
- package/src/contract/flow-run.ts +241 -0
- package/src/contract/flow.ts +675 -0
- package/src/contract/node.ts +583 -0
- package/src/contract/share.ts +196 -0
- package/src/contract/table.ts +178 -0
- package/src/contract/tool.ts +202 -0
- package/ui/README.md +110 -0
- package/ui/components.json +21 -0
- package/ui/index.html +13 -0
- package/ui/package.json +11 -0
- package/ui/scripts/lint-tokens.mjs +187 -0
- package/ui/src/access-summary/access-summary.tsx +385 -0
- package/ui/src/app/action-slot/action-slot.tsx +27 -0
- package/ui/src/app/app-sidebar/app-sidebar.tsx +71 -0
- package/ui/src/app/app-tree/app-tree.tsx +1175 -0
- package/ui/src/app/app.tsx +87 -0
- package/ui/src/app/header-search/header-search.tsx +294 -0
- package/ui/src/app/reindex-dialog/reindex-dialog.tsx +79 -0
- package/ui/src/app/settings-dialog/settings-dialog.tsx +135 -0
- package/ui/src/app/sidebar-preferences/sidebar-preferences.ts +68 -0
- package/ui/src/app/sidebar-preferences/sidebar-preferences.types.ts +15 -0
- package/ui/src/app/sidebar-resize-handle/sidebar-resize-handle.tsx +86 -0
- package/ui/src/app/tree-expansion/tree-expansion.ts +107 -0
- package/ui/src/app/tree-expansion/tree-expansion.types.ts +31 -0
- package/ui/src/app/tree-move/tree-move.tsx +427 -0
- package/ui/src/app/tree-reveal/tree-reveal.ts +64 -0
- package/ui/src/app/tree-reveal/tree-reveal.types.ts +16 -0
- package/ui/src/app/user-footer/user-footer.tsx +188 -0
- package/ui/src/app/view-menu/view-menu.tsx +115 -0
- package/ui/src/app-root/app-root.tsx +109 -0
- package/ui/src/app-root/app-root.types.ts +27 -0
- package/ui/src/archive/archive.tsx +417 -0
- package/ui/src/attachment-detail/attachment-detail.ts +52 -0
- package/ui/src/attachment-viewer/attachment-viewer.tsx +166 -0
- package/ui/src/blocknote-view/blocknote-view.tsx +30 -0
- package/ui/src/board/board-assignee/board-assignee-picker.tsx +132 -0
- package/ui/src/board/board-assignee/board-assignee.ts +48 -0
- package/ui/src/board/board-assignee/board-assignee.tsx +75 -0
- package/ui/src/board/board-chip/board-chip.tsx +46 -0
- package/ui/src/board/board-crumbs/board-crumbs.ts +56 -0
- package/ui/src/board/board-crumbs/board-crumbs.tsx +111 -0
- package/ui/src/board/board-data/board-data.ts +195 -0
- package/ui/src/board/board-data/board-data.types.ts +38 -0
- package/ui/src/board/board-dates/board-dates.ts +40 -0
- package/ui/src/board/board-dates/board-dates.tsx +105 -0
- package/ui/src/board/board-kanban/board-kanban.ts +162 -0
- package/ui/src/board/board-kanban/board-kanban.tsx +680 -0
- package/ui/src/board/board-open-task/board-open-task.ts +32 -0
- package/ui/src/board/board-panel/board-panel.tsx +259 -0
- package/ui/src/board/board-settings/board-settings.tsx +226 -0
- package/ui/src/board/board-status/board-status.tsx +60 -0
- package/ui/src/board/board-stripes/board-stripes.ts +128 -0
- package/ui/src/board/board-table/board-table.ts +53 -0
- package/ui/src/board/board-table/board-table.tsx +610 -0
- package/ui/src/board/board-task/board-task.ts +108 -0
- package/ui/src/board/board-task/board-task.tsx +335 -0
- package/ui/src/board/board-title-row/board-title-row.tsx +66 -0
- package/ui/src/branding/branding.tsx +17 -0
- package/ui/src/branding/custom-logo.ts +1 -0
- package/ui/src/branding/favicon.default.svg +5 -0
- package/ui/src/branding/favicon.svg +5 -0
- package/ui/src/components/ui/avatar.tsx +39 -0
- package/ui/src/components/ui/button.tsx +64 -0
- package/ui/src/components/ui/collapsible.tsx +20 -0
- package/ui/src/components/ui/command.tsx +160 -0
- package/ui/src/components/ui/dialog.tsx +143 -0
- package/ui/src/components/ui/dropdown-menu.tsx +187 -0
- package/ui/src/components/ui/input.tsx +21 -0
- package/ui/src/components/ui/popover.tsx +41 -0
- package/ui/src/components/ui/select.tsx +163 -0
- package/ui/src/components/ui/separator.tsx +26 -0
- package/ui/src/components/ui/sheet.tsx +136 -0
- package/ui/src/components/ui/sidebar.tsx +693 -0
- package/ui/src/components/ui/skeleton.tsx +13 -0
- package/ui/src/components/ui/switch.tsx +25 -0
- package/ui/src/components/ui/table.tsx +82 -0
- package/ui/src/components/ui/tabs.tsx +52 -0
- package/ui/src/components/ui/tooltip.tsx +51 -0
- package/ui/src/data/intel-data-provider/intel-data-provider.ts +685 -0
- package/ui/src/data/intel-data-provider/intel-data-provider.types.ts +266 -0
- package/ui/src/data/query-client.ts +18 -0
- package/ui/src/data/request-refusal/refusal-notice.tsx +36 -0
- package/ui/src/data/request-refusal/request-refusal.ts +51 -0
- package/ui/src/data/sign-in/sign-in.ts +97 -0
- package/ui/src/data/sign-in/sign-in.types.ts +15 -0
- package/ui/src/document-link/document-link.tsx +114 -0
- package/ui/src/document-markdown/document-markdown.ts +195 -0
- package/ui/src/editor-schema/editor-schema.ts +23 -0
- package/ui/src/entry-picker/entry-picker.tsx +238 -0
- package/ui/src/feed/feed.tsx +344 -0
- package/ui/src/file-preview/file-preview-view.tsx +496 -0
- package/ui/src/file-preview/file-preview.tsx +28 -0
- package/ui/src/file-preview/pdf-file-preview.tsx +5 -0
- package/ui/src/file-preview/presentation-file-preview.tsx +21 -0
- package/ui/src/file-preview/spreadsheet-file-preview.tsx +5 -0
- package/ui/src/file-preview/word-file-preview.tsx +5 -0
- package/ui/src/flow-runs/flow-runs.tsx +238 -0
- package/ui/src/flows/flows.tsx +1646 -0
- package/ui/src/flows/node-icon/node-icon.ts +34 -0
- package/ui/src/flows/node-palette/node-palette.tsx +214 -0
- package/ui/src/flows/node-palette/node-palette.types.ts +15 -0
- package/ui/src/folder-contents/folder-contents.tsx +321 -0
- package/ui/src/folder-index/folder-index.ts +55 -0
- package/ui/src/frontmatter/frontmatter.tsx +193 -0
- package/ui/src/graph-pane/graph-pane.tsx +53 -0
- package/ui/src/hooks/use-mobile.ts +19 -0
- package/ui/src/i18n/custom.json +4 -0
- package/ui/src/i18n/de.json +609 -0
- package/ui/src/i18n/en.json +609 -0
- package/ui/src/i18n/es.json +609 -0
- package/ui/src/i18n/i18n-context.tsx +65 -0
- package/ui/src/i18n/i18n-languages/i18n-languages.ts +83 -0
- package/ui/src/i18n/i18n.ts +32 -0
- package/ui/src/i18n/i18n.types.ts +49 -0
- package/ui/src/kind-icon.ts +97 -0
- package/ui/src/lib/utils.ts +6 -0
- package/ui/src/main.tsx +68 -0
- package/ui/src/modal/modal.tsx +53 -0
- package/ui/src/node-details/node-details.tsx +545 -0
- package/ui/src/node-editor/node-editor.tsx +304 -0
- package/ui/src/node-graph/graph-notice.tsx +21 -0
- package/ui/src/node-graph/node-graph.ts +214 -0
- package/ui/src/node-graph/node-graph.tsx +295 -0
- package/ui/src/node-import/node-import.tsx +418 -0
- package/ui/src/node-save-error.ts +46 -0
- package/ui/src/node-source/node-source.tsx +128 -0
- package/ui/src/node-table/node-table.tsx +107 -0
- package/ui/src/nodes/nodes.tsx +240 -0
- package/ui/src/rename-resource/rename-resource.ts +80 -0
- package/ui/src/resolved-names/resolved-names.tsx +67 -0
- package/ui/src/resource-error.ts +33 -0
- package/ui/src/resource-menu/resource-menu.tsx +1156 -0
- package/ui/src/router/router-context.ts +6 -0
- package/ui/src/router/router.tsx +67 -0
- package/ui/src/router/router.types.ts +8 -0
- package/ui/src/router/selection-search.ts +88 -0
- package/ui/src/save-button/save-button.tsx +94 -0
- package/ui/src/section-hint/section-hint.tsx +40 -0
- package/ui/src/sign-in-refused/sign-in-refused.tsx +35 -0
- package/ui/src/styles.css +189 -0
- package/ui/src/table-columns/table-columns.tsx +379 -0
- package/ui/src/theme/custom.css +1 -0
- package/ui/src/theme/theme-context.tsx +89 -0
- package/ui/src/theme/theme.ts +70 -0
- package/ui/src/time/relative-time.tsx +41 -0
- package/ui/src/time/time-context.tsx +78 -0
- package/ui/src/time/time.ts +165 -0
- package/ui/src/title-row/title-row.tsx +185 -0
- package/ui/src/tools/tools.tsx +546 -0
- package/ui/src/user-name/user-name.ts +61 -0
- package/ui/src/verbatim/verbatim.tsx +68 -0
- package/ui/tsconfig.json +17 -0
- package/ui/vite.config.ts +129 -0
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { IdempotencyKey, IntelId, IsoDateTime } from "./contract.js";
|
|
3
|
+
// One column of a board. `terminal` is what "done" means here — a rule about the column rather than
|
|
4
|
+
// a magic status name, so an installation may call it "Shipped" or "Abgerechnet" without anything
|
|
5
|
+
// downstream having to know the word.
|
|
6
|
+
/**
|
|
7
|
+
* The id of the archive column, on every board (D68, #674).
|
|
8
|
+
*
|
|
9
|
+
* ⚠️ **It is derived, never stored.** A card sits in it because `nodes.archived_at` is set, and
|
|
10
|
+
* `board_tasks.status` keeps naming the working column it came from — that is what lets a card
|
|
11
|
+
* pulled back out land where it was. A configured column may not claim this id; `board_update`
|
|
12
|
+
* refuses it, because two columns with one id means every card in them lands in whichever the view
|
|
13
|
+
* draws first.
|
|
14
|
+
*/
|
|
15
|
+
export const ARCHIVE_COLUMN_ID = "archived";
|
|
16
|
+
/**
|
|
17
|
+
* What a colour picker starts on for a column that has none (#725).
|
|
18
|
+
*
|
|
19
|
+
* ⚠️ **Here rather than in the browser package, and that is not tidiness.** The token linter refuses
|
|
20
|
+
* a hard-coded hex in `packages/intel/ui`, and it is right to: a colour written into a component bypasses
|
|
21
|
+
* the theme. This one is not a theme colour, it is DATA — the value a person is about to choose
|
|
22
|
+
* from and the api writes as a default — so it belongs where both sides may read it, which is here.
|
|
23
|
+
*
|
|
24
|
+
* ⚠️ **It is the widget's starting point, never a written value.** `color` stays absent until
|
|
25
|
+
* somebody picks one, so opening the dialog does not repaint a board that predates colours.
|
|
26
|
+
*/
|
|
27
|
+
export const DEFAULT_COLUMN_COLOR = "#9ca3af";
|
|
28
|
+
export const BoardColumn = z.strictObject({
|
|
29
|
+
id: z.string().min(1).max(60).describe("Stable key stored on every task in this column."),
|
|
30
|
+
title: z.string().min(1).max(80).describe("What the column is called on screen."),
|
|
31
|
+
terminal: z
|
|
32
|
+
.boolean()
|
|
33
|
+
.default(false)
|
|
34
|
+
.describe("Whether a task in this column counts as finished. More than one column may be."),
|
|
35
|
+
/**
|
|
36
|
+
* ⚠️ **The colour belongs to the COLUMN, never to the card** (#725, and #365 took the status dot
|
|
37
|
+
* off the card on purpose). A card is in a column; drawing the column's colour on it would be the
|
|
38
|
+
* same fact twice, and the second copy is the one that goes stale.
|
|
39
|
+
*
|
|
40
|
+
* A free value rather than a fixed palette (Jack's decision 2026-08-22). It only ever fills a
|
|
41
|
+
* DOT, so a badly chosen one is hard to see but makes nothing unreadable — which is what makes a
|
|
42
|
+
* free choice affordable here and would not make it affordable behind text.
|
|
43
|
+
*/
|
|
44
|
+
color: z
|
|
45
|
+
.string()
|
|
46
|
+
.regex(/^#[0-9a-fA-F]{6}$/, "A colour is six hex digits behind a hash, like #6b7280.")
|
|
47
|
+
.optional()
|
|
48
|
+
.describe("The dot in front of this column's title, and in front of a linked task that sits in it. Six hex digits behind a hash. Absent means the reader's own default, so an older board is not repainted by this field appearing."),
|
|
49
|
+
});
|
|
50
|
+
// One card, as the board view needs it: everything to draw and sort by, and NOTHING from R2. The
|
|
51
|
+
// body is fetched per task through `node_version_get` when somebody opens one.
|
|
52
|
+
//
|
|
53
|
+
// ⚠️ `position` is a float, not an index. Dropping a card between two neighbours is then the
|
|
54
|
+
// midpoint of the two, and no other row is written. With integers every drop would renumber
|
|
55
|
+
// everything below it, and two people dropping at once would fight over rows neither touched.
|
|
56
|
+
export const BoardTask = z.strictObject({
|
|
57
|
+
id: IntelId.describe("The card's node id — its address everywhere else in Intel."),
|
|
58
|
+
title: z.string().min(1).max(240).describe("What the card says."),
|
|
59
|
+
status: z.string().min(1).max(60).describe("Which column it sits in."),
|
|
60
|
+
assigneeId: z.string().min(1).nullable(),
|
|
61
|
+
labels: z.array(z.string().min(1).max(40)),
|
|
62
|
+
startDate: IsoDateTime.nullable(),
|
|
63
|
+
dueDate: IsoDateTime.nullable(),
|
|
64
|
+
dependsOn: IntelId.nullable(),
|
|
65
|
+
/**
|
|
66
|
+
* The task this one sits under, or `null` when it sits directly on the board.
|
|
67
|
+
*
|
|
68
|
+
* ⚠️ **The hierarchy is the node tree** (`nodes.parent_id`), not a second column here — a task
|
|
69
|
+
* under a task IS the tree Intel already has, which is why the cycle guard that refuses moving a
|
|
70
|
+
* node into its own descendant covers this for free.
|
|
71
|
+
*
|
|
72
|
+
* ⚠️ **Under a filter this may name a task that is not in the same answer.** `board_get` returns
|
|
73
|
+
* what matches; a subtask can match while its parent does not. A reader that assumes the parent
|
|
74
|
+
* is present will lose the row — treat an unknown parent as top level.
|
|
75
|
+
*/
|
|
76
|
+
parentTaskId: IntelId.nullable(),
|
|
77
|
+
position: z.number(),
|
|
78
|
+
archivedAt: IsoDateTime.nullable(),
|
|
79
|
+
});
|
|
80
|
+
// ⚠️ Every filter here is a COLUMN in `board_tasks`, and that is the whole reason the fields are not
|
|
81
|
+
// in the body. A filter the application applies after reading has already fetched the rows — over
|
|
82
|
+
// the wire, into memory, past the point where leaving them out would have helped.
|
|
83
|
+
export const BoardTaskFilter = z.strictObject({
|
|
84
|
+
status: z
|
|
85
|
+
.string()
|
|
86
|
+
.min(1)
|
|
87
|
+
.max(60)
|
|
88
|
+
.optional()
|
|
89
|
+
.describe("Only tasks in this column. Omit for every column."),
|
|
90
|
+
assigneeId: z
|
|
91
|
+
.string()
|
|
92
|
+
.min(1)
|
|
93
|
+
.optional()
|
|
94
|
+
.describe("Only tasks assigned to this Gate principal. An agent is not a special case here."),
|
|
95
|
+
dueBefore: IsoDateTime.optional().describe("Only tasks due strictly before this moment. Tasks without a due date never match."),
|
|
96
|
+
dependsOn: IntelId.optional().describe("Only tasks waiting for this node — what `board_get` answers when you ask what one thing blocks."),
|
|
97
|
+
includeArchived: z
|
|
98
|
+
.boolean()
|
|
99
|
+
.default(false)
|
|
100
|
+
.describe("Include archived tasks beside the live ones instead of hiding them."),
|
|
101
|
+
});
|
|
102
|
+
export const BoardGetInput = BoardTaskFilter.extend({
|
|
103
|
+
boardId: IntelId.describe("The board node to read. Must be a node of kind `board`."),
|
|
104
|
+
});
|
|
105
|
+
// One answer for the whole board, not one per card.
|
|
106
|
+
export const BoardView = z.strictObject({
|
|
107
|
+
boardId: IntelId,
|
|
108
|
+
title: z.string().min(1).max(240),
|
|
109
|
+
columns: z.array(BoardColumn),
|
|
110
|
+
/**
|
|
111
|
+
* Whether the archive column is drawn (D68, #674).
|
|
112
|
+
*
|
|
113
|
+
* ⚠️ It travels even when it is `false`, because the settings dialog needs to draw the switch in
|
|
114
|
+
* both positions — and because "the column is not in `columns`" has two possible reasons, hidden
|
|
115
|
+
* and not-yet-supported, which a reader cannot tell apart from the list alone.
|
|
116
|
+
*/
|
|
117
|
+
archiveVisible: z.boolean(),
|
|
118
|
+
tasks: z.array(BoardTask),
|
|
119
|
+
});
|
|
120
|
+
export const BoardUpdateInput = z.strictObject({
|
|
121
|
+
boardId: IntelId.describe("The board node whose columns are being set."),
|
|
122
|
+
columns: z
|
|
123
|
+
.array(BoardColumn)
|
|
124
|
+
.min(1)
|
|
125
|
+
.describe(`The complete new column list, in order. Columns are replaced, not merged. The archive column (\`${ARCHIVE_COLUMN_ID}\`) is not part of this list and cannot be named in it — it is on every board and is only shown or hidden.`),
|
|
126
|
+
// ⚠️ Shown or hidden, never removed. The archive is the same place on every board; a shelf that
|
|
127
|
+
// could be dragged between the working columns would be a shelf pretending to be a stage.
|
|
128
|
+
archiveVisible: z
|
|
129
|
+
.boolean()
|
|
130
|
+
.optional()
|
|
131
|
+
.describe("Whether the archive column is drawn. Omit to leave it as it is."),
|
|
132
|
+
idempotencyKey: IdempotencyKey,
|
|
133
|
+
});
|
|
134
|
+
export const BoardTaskCreateInput = z.strictObject({
|
|
135
|
+
boardId: IntelId.describe("The board the task is filed under. It becomes the task's parent."),
|
|
136
|
+
title: z.string().min(1).max(240).describe("What the card says on the board."),
|
|
137
|
+
// ⚠️ Optional, and absent means the FIRST column rather than an error. A caller who does not care
|
|
138
|
+
// where a task starts should not have to read the board first — and a task with no status would
|
|
139
|
+
// be a card no view can draw.
|
|
140
|
+
status: z
|
|
141
|
+
.string()
|
|
142
|
+
.min(1)
|
|
143
|
+
.max(60)
|
|
144
|
+
.optional()
|
|
145
|
+
.describe("Which column to file it in. Omit for the board's first column."),
|
|
146
|
+
assigneeId: z
|
|
147
|
+
.string()
|
|
148
|
+
.min(1)
|
|
149
|
+
.nullable()
|
|
150
|
+
.default(null)
|
|
151
|
+
.describe("Who it is for, as a Gate principal id. An agent is not a special case."),
|
|
152
|
+
labels: z
|
|
153
|
+
.array(z.string().min(1).max(40))
|
|
154
|
+
.default([])
|
|
155
|
+
.describe("Free-form tags. They are filtered on the board, not in search."),
|
|
156
|
+
startDate: IsoDateTime.nullable()
|
|
157
|
+
.default(null)
|
|
158
|
+
.describe("When work on it should begin. Only the timeline view draws it."),
|
|
159
|
+
dueDate: IsoDateTime.nullable()
|
|
160
|
+
.default(null)
|
|
161
|
+
.describe("When it is due. A card without one never matches a due-before filter."),
|
|
162
|
+
dependsOn: IntelId.nullable()
|
|
163
|
+
.default(null)
|
|
164
|
+
.describe("A node this task waits for. Any node, not only another task."),
|
|
165
|
+
// ⚠️ Creating a subtask is ONE call; moving an existing task under another is `node_update`
|
|
166
|
+
// with a new `parentId`. Two paths for "where a task sits" would mean two cycle guards, and the
|
|
167
|
+
// one on the node path is the one that already exists.
|
|
168
|
+
parentTaskId: IntelId.nullable()
|
|
169
|
+
.default(null)
|
|
170
|
+
.describe("The task this one belongs under. It must be on the same board. Omit for a card that sits directly on the board."),
|
|
171
|
+
idempotencyKey: IdempotencyKey,
|
|
172
|
+
});
|
|
173
|
+
// ⚠️ Moving a card IS this call: `status` and `position` together. There is deliberately no
|
|
174
|
+
// `board_task_move` — it would be a second way to write one row, and a model reading `tools/list`
|
|
175
|
+
// would have to guess which of the two applies.
|
|
176
|
+
//
|
|
177
|
+
// Every field is optional and absent means "leave it": a drag sends two fields, a rename sends one.
|
|
178
|
+
// `null` is a value where the column is nullable, so clearing a due date is `dueDate: null` and not
|
|
179
|
+
// its absence.
|
|
180
|
+
export const BoardTaskUpdateInput = z.strictObject({
|
|
181
|
+
taskId: IntelId.describe("The card to change, by its node id."),
|
|
182
|
+
title: z
|
|
183
|
+
.string()
|
|
184
|
+
.min(1)
|
|
185
|
+
.max(240)
|
|
186
|
+
.optional()
|
|
187
|
+
.describe("Refused on purpose: a card's title lives on the node. Rename it with node_update."),
|
|
188
|
+
status: z
|
|
189
|
+
.string()
|
|
190
|
+
.min(1)
|
|
191
|
+
.max(60)
|
|
192
|
+
.optional()
|
|
193
|
+
.describe(`The column to move it to. \`${ARCHIVE_COLUMN_ID}\` is not an ordinary column: it archives the card through the same path as \`node_archive\`, with the same refusals — a card that still has live subtasks is refused. Moving it to any other column while it is archived brings it back.`),
|
|
194
|
+
position: z
|
|
195
|
+
.number()
|
|
196
|
+
.optional()
|
|
197
|
+
.describe("Where in the column. Use the midpoint between the two neighbours it lands between."),
|
|
198
|
+
assigneeId: z
|
|
199
|
+
.string()
|
|
200
|
+
.min(1)
|
|
201
|
+
.nullable()
|
|
202
|
+
.optional()
|
|
203
|
+
.describe("Who it is for. `null` unassigns it; leaving it out keeps whoever has it."),
|
|
204
|
+
labels: z
|
|
205
|
+
.array(z.string().min(1).max(40))
|
|
206
|
+
.optional()
|
|
207
|
+
.describe("The complete new tag list. Tags are replaced, not merged."),
|
|
208
|
+
startDate: IsoDateTime.nullable()
|
|
209
|
+
.optional()
|
|
210
|
+
.describe("When work should begin. `null` clears it."),
|
|
211
|
+
dueDate: IsoDateTime.nullable().optional().describe("When it is due. `null` clears it."),
|
|
212
|
+
dependsOn: IntelId.nullable()
|
|
213
|
+
.optional()
|
|
214
|
+
.describe("A node this card waits for. `null` clears the dependency."),
|
|
215
|
+
idempotencyKey: IdempotencyKey,
|
|
216
|
+
});
|
|
217
|
+
// ── Who a card can be given to ────────────────────────────────────────────────────────────────
|
|
218
|
+
// D70 (`~/Dev/anchrd/core/DECISIONS.md`): the people offered here are the ones who can actually open
|
|
219
|
+
// THIS board, never everyone who holds an account. The narrower answer is the point, and it is what
|
|
220
|
+
// makes the door safe to offer to anyone who can see the board.
|
|
221
|
+
//
|
|
222
|
+
// ⚠️ `email` travels because two colleagues share a first name more often than a picker can afford,
|
|
223
|
+
// and a list of indistinguishable "Anton" rows is not a picker. It is no wider than what gate hands
|
|
224
|
+
// any signed-in person at `POST /directory/search`; the narrowing this door adds is WHO appears,
|
|
225
|
+
// not WHAT is said about them.
|
|
226
|
+
//
|
|
227
|
+
// `isMachine` travels for the same reason gate carries it: whoever picks an assignee wants to know
|
|
228
|
+
// whether they are handing the card to a colleague or to an agent.
|
|
229
|
+
export const DirectoryPerson = z.strictObject({
|
|
230
|
+
id: IntelId,
|
|
231
|
+
name: z.string(),
|
|
232
|
+
email: z.email(),
|
|
233
|
+
isMachine: z.boolean(),
|
|
234
|
+
});
|
|
235
|
+
export const BoardAssigneeSearchInput = z.strictObject({
|
|
236
|
+
boardId: IntelId.describe("The board whose people to offer. Only those who can open this board appear, so the same query against two boards can give two different answers."),
|
|
237
|
+
query: z
|
|
238
|
+
.string()
|
|
239
|
+
.describe("What was typed. EMPTY names up to three people who reach this board, so a picker can open with suggestions instead of nothing. One character answers empty rather than everybody: a single letter is a listing under a different name, while an empty query asks for a bounded set this board already knows."),
|
|
240
|
+
});
|
|
241
|
+
// ⚠️ A DIFFERENT question from the one above, and deliberately not board-scoped. This one names
|
|
242
|
+
// people who are ALREADY recorded on a card, so that a circle can carry initials instead of a raw
|
|
243
|
+
// id (`#258`). Someone whose access was withdrawn, or whose account was switched off, still has to
|
|
244
|
+
// be nameable: a card that reads as unassigned is a worse answer than the truth.
|
|
245
|
+
export const DirectoryResolveInput = z.strictObject({
|
|
246
|
+
ids: z
|
|
247
|
+
.array(IntelId)
|
|
248
|
+
.min(1)
|
|
249
|
+
.max(100)
|
|
250
|
+
.describe("The ids to name. Ids that cannot be named are absent from the answer rather than reported, and more than a hundred is refused rather than silently shortened."),
|
|
251
|
+
});
|
|
252
|
+
export const DirectoryPersonList = z.strictObject({
|
|
253
|
+
items: z.array(DirectoryPerson),
|
|
254
|
+
/**
|
|
255
|
+
* ⚠️ **How many are left over, so the cap is visible rather than silent** (#757). Three suggestions
|
|
256
|
+
* that look like the whole list are worse than three that say "and 4 more": the first teaches the
|
|
257
|
+
* reader that nobody else exists.
|
|
258
|
+
*
|
|
259
|
+
* `0` on a search answer, where the cap is gate's own and this door does not own it.
|
|
260
|
+
*/
|
|
261
|
+
more: z.number().int().min(0).default(0),
|
|
262
|
+
});
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const BundleManifestFilename = "manifest.json";
|
|
3
|
+
/**
|
|
4
|
+
* What a bundle entry can be. `flow` joins the node kinds because a flow shares the folder tree
|
|
5
|
+
* without being a node (ADR-0004), and the bundle mirrors the tree, not the tables.
|
|
6
|
+
*
|
|
7
|
+
* ⚠️ `agent` and `board` are STILL HERE, and that is the one place in this file where a value
|
|
8
|
+
* survives its feature (#390). A bundle is somebody else's file: an export written before Agents
|
|
9
|
+
* and Board were parked (#385) is a correct export, and it has to PARSE so the import can refuse it
|
|
10
|
+
* by name — with the entry, the kind and the branch the code is on. Take them out and the same
|
|
11
|
+
* bundle fails as `unexpected enum value`, which sends its holder looking for a broken file that is
|
|
12
|
+
* not broken.
|
|
13
|
+
*
|
|
14
|
+
* They belong to the wire format of a file that already exists, not to the product. Nothing may
|
|
15
|
+
* create either kind; `NodeKind` is the enum that says so.
|
|
16
|
+
*/
|
|
17
|
+
export declare const BundleEntryKind: z.ZodEnum<{
|
|
18
|
+
folder: "folder";
|
|
19
|
+
document: "document";
|
|
20
|
+
attachment: "attachment";
|
|
21
|
+
table: "table";
|
|
22
|
+
board: "board";
|
|
23
|
+
flow: "flow";
|
|
24
|
+
agent: "agent";
|
|
25
|
+
}>;
|
|
26
|
+
export type BundleEntryKind = z.infer<typeof BundleEntryKind>;
|
|
27
|
+
/**
|
|
28
|
+
* Why an entry carries no bytes although its kind normally does (#534).
|
|
29
|
+
*
|
|
30
|
+
* `no-content` is a node that has never been given any: a table created but never defined has no
|
|
31
|
+
* version, and an attachment created but never uploaded has none either, so there is nothing to
|
|
32
|
+
* write. That is a different sentence from "the content is gone", which the export refuses as
|
|
33
|
+
* `content_missing` — and a file of zero bytes cannot say which of the two it is, which is exactly
|
|
34
|
+
* what it used to do.
|
|
35
|
+
*/
|
|
36
|
+
export declare const BundleEntryAbsence: z.ZodEnum<{
|
|
37
|
+
"no-content": "no-content";
|
|
38
|
+
}>;
|
|
39
|
+
export type BundleEntryAbsence = z.infer<typeof BundleEntryAbsence>;
|
|
40
|
+
export declare const BundleManifestEntry: z.ZodObject<{
|
|
41
|
+
id: z.ZodString;
|
|
42
|
+
kind: z.ZodEnum<{
|
|
43
|
+
folder: "folder";
|
|
44
|
+
document: "document";
|
|
45
|
+
attachment: "attachment";
|
|
46
|
+
table: "table";
|
|
47
|
+
board: "board";
|
|
48
|
+
flow: "flow";
|
|
49
|
+
agent: "agent";
|
|
50
|
+
}>;
|
|
51
|
+
title: z.ZodString;
|
|
52
|
+
description: z.ZodNullable<z.ZodString>;
|
|
53
|
+
mediaType: z.ZodNullable<z.ZodString>;
|
|
54
|
+
path: z.ZodString;
|
|
55
|
+
absence: z.ZodOptional<z.ZodEnum<{
|
|
56
|
+
"no-content": "no-content";
|
|
57
|
+
}>>;
|
|
58
|
+
}, z.core.$strict>;
|
|
59
|
+
export type BundleManifestEntry = z.infer<typeof BundleManifestEntry>;
|
|
60
|
+
/**
|
|
61
|
+
* What an export leaves out on purpose, named so a bundle says it rather than a reader guessing:
|
|
62
|
+
* version history, grants/shares, flow runs, and archived nodes are not in any bundle (#136).
|
|
63
|
+
*
|
|
64
|
+
* ⚠️ `unpublished-flow-changes` is the FIFTH, and it is the one exception to ADR-0006's own
|
|
65
|
+
* headline (#585). A bundle carries the current state of everything — except a flow that has been
|
|
66
|
+
* published, which travels as its PUBLISHED graph. Edits made after that publication are in no
|
|
67
|
+
* bundle, and they are not history: they are the newest state there is. The word exists because the
|
|
68
|
+
* loss is only acceptable while it is named, and `version-history` does not name it — a reader who
|
|
69
|
+
* saw only that word would expect the newest graph and get one that is deliberately older.
|
|
70
|
+
*
|
|
71
|
+
* ⚠️ These are WIRE values: an older reader refuses a bundle naming an exclusion it does not know,
|
|
72
|
+
* the same way it would refuse an unknown `kind`. The enum grows only for something an installation
|
|
73
|
+
* genuinely leaves behind, never as a place to note a nicety (ADR-0006, #433). Growing it costs the
|
|
74
|
+
* direction nobody migrates in — a bundle written HERE is refused by an installation older than
|
|
75
|
+
* this line, while every bundle written before it still parses, which is the direction 0.22.0's
|
|
76
|
+
* rebuild actually runs.
|
|
77
|
+
*/
|
|
78
|
+
export declare const BundleExclusion: z.ZodEnum<{
|
|
79
|
+
"version-history": "version-history";
|
|
80
|
+
grants: "grants";
|
|
81
|
+
"flow-runs": "flow-runs";
|
|
82
|
+
"archived-nodes": "archived-nodes";
|
|
83
|
+
"unpublished-flow-changes": "unpublished-flow-changes";
|
|
84
|
+
}>;
|
|
85
|
+
export type BundleExclusion = z.infer<typeof BundleExclusion>;
|
|
86
|
+
export declare const BundleManifest: z.ZodObject<{
|
|
87
|
+
version: z.ZodLiteral<1>;
|
|
88
|
+
exportedAt: z.ZodISODateTime;
|
|
89
|
+
rootId: z.ZodNullable<z.ZodString>;
|
|
90
|
+
entries: z.ZodArray<z.ZodObject<{
|
|
91
|
+
id: z.ZodString;
|
|
92
|
+
kind: z.ZodEnum<{
|
|
93
|
+
folder: "folder";
|
|
94
|
+
document: "document";
|
|
95
|
+
attachment: "attachment";
|
|
96
|
+
table: "table";
|
|
97
|
+
board: "board";
|
|
98
|
+
flow: "flow";
|
|
99
|
+
agent: "agent";
|
|
100
|
+
}>;
|
|
101
|
+
title: z.ZodString;
|
|
102
|
+
description: z.ZodNullable<z.ZodString>;
|
|
103
|
+
mediaType: z.ZodNullable<z.ZodString>;
|
|
104
|
+
path: z.ZodString;
|
|
105
|
+
absence: z.ZodOptional<z.ZodEnum<{
|
|
106
|
+
"no-content": "no-content";
|
|
107
|
+
}>>;
|
|
108
|
+
}, z.core.$strict>>;
|
|
109
|
+
excluded: z.ZodArray<z.ZodEnum<{
|
|
110
|
+
"version-history": "version-history";
|
|
111
|
+
grants: "grants";
|
|
112
|
+
"flow-runs": "flow-runs";
|
|
113
|
+
"archived-nodes": "archived-nodes";
|
|
114
|
+
"unpublished-flow-changes": "unpublished-flow-changes";
|
|
115
|
+
}>>;
|
|
116
|
+
}, z.core.$strict>;
|
|
117
|
+
export type BundleManifest = z.infer<typeof BundleManifest>;
|
|
118
|
+
/**
|
|
119
|
+
* What one import made. Import always creates new nodes — no merge, no overwrite, no restored IDs
|
|
120
|
+
* (#137, phase 1) — so the answer is counts and the new roots, never a diff. `replayed` marks the
|
|
121
|
+
* idempotent second answer to the same key: nothing was created twice.
|
|
122
|
+
*
|
|
123
|
+
* ⚠️ `excluded` is what the IMPORT knows about itself, never what the bundle claimed (ADR-0006,
|
|
124
|
+
* #433). A subtree moved between installations arrives with one version per node, no grants and no
|
|
125
|
+
* runs, and until now nothing said so at the moment somebody could still act on it — the word stood
|
|
126
|
+
* only in a `manifest.json` inside the zip that had already been written.
|
|
127
|
+
*
|
|
128
|
+
* It is deliberately NOT read back out of that manifest. A hand-written bundle saying `excluded: []`
|
|
129
|
+
* would then make the import report that nothing was left behind, and the import would launder
|
|
130
|
+
* somebody else's claim into an answer that sounds like its own — the trap `absence` is bound
|
|
131
|
+
* against in `BundleManifestEntry` above (#534, #560). The five exclusions hold for every import
|
|
132
|
+
* this build performs, with a manifest or from a naked folder, so this is a constant of the code.
|
|
133
|
+
*/
|
|
134
|
+
export declare const BundleImportResult: z.ZodObject<{
|
|
135
|
+
nodes: z.ZodNumber;
|
|
136
|
+
flows: z.ZodNumber;
|
|
137
|
+
rootNodeIds: z.ZodArray<z.ZodString>;
|
|
138
|
+
replayed: z.ZodBoolean;
|
|
139
|
+
excluded: z.ZodArray<z.ZodEnum<{
|
|
140
|
+
"version-history": "version-history";
|
|
141
|
+
grants: "grants";
|
|
142
|
+
"flow-runs": "flow-runs";
|
|
143
|
+
"archived-nodes": "archived-nodes";
|
|
144
|
+
"unpublished-flow-changes": "unpublished-flow-changes";
|
|
145
|
+
}>>;
|
|
146
|
+
}, z.core.$strict>;
|
|
147
|
+
export type BundleImportResult = z.infer<typeof BundleImportResult>;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { IntelId, IsoDateTime } from "./contract.js";
|
|
3
|
+
// ── Bundle export (#136) ────────────────────────────────────────────────────────────────────────
|
|
4
|
+
// The one name the importer looks for at the zip root. A different spelling would make a bundle a
|
|
5
|
+
// naked folder, so the constant lives in the contract rather than in each surface.
|
|
6
|
+
export const BundleManifestFilename = "manifest.json";
|
|
7
|
+
/**
|
|
8
|
+
* What a bundle entry can be. `flow` joins the node kinds because a flow shares the folder tree
|
|
9
|
+
* without being a node (ADR-0004), and the bundle mirrors the tree, not the tables.
|
|
10
|
+
*
|
|
11
|
+
* ⚠️ `agent` and `board` are STILL HERE, and that is the one place in this file where a value
|
|
12
|
+
* survives its feature (#390). A bundle is somebody else's file: an export written before Agents
|
|
13
|
+
* and Board were parked (#385) is a correct export, and it has to PARSE so the import can refuse it
|
|
14
|
+
* by name — with the entry, the kind and the branch the code is on. Take them out and the same
|
|
15
|
+
* bundle fails as `unexpected enum value`, which sends its holder looking for a broken file that is
|
|
16
|
+
* not broken.
|
|
17
|
+
*
|
|
18
|
+
* They belong to the wire format of a file that already exists, not to the product. Nothing may
|
|
19
|
+
* create either kind; `NodeKind` is the enum that says so.
|
|
20
|
+
*/
|
|
21
|
+
export const BundleEntryKind = z.enum([
|
|
22
|
+
"folder",
|
|
23
|
+
"document",
|
|
24
|
+
"table",
|
|
25
|
+
"attachment",
|
|
26
|
+
"agent",
|
|
27
|
+
"board",
|
|
28
|
+
"flow",
|
|
29
|
+
]);
|
|
30
|
+
/**
|
|
31
|
+
* Why an entry carries no bytes although its kind normally does (#534).
|
|
32
|
+
*
|
|
33
|
+
* `no-content` is a node that has never been given any: a table created but never defined has no
|
|
34
|
+
* version, and an attachment created but never uploaded has none either, so there is nothing to
|
|
35
|
+
* write. That is a different sentence from "the content is gone", which the export refuses as
|
|
36
|
+
* `content_missing` — and a file of zero bytes cannot say which of the two it is, which is exactly
|
|
37
|
+
* what it used to do.
|
|
38
|
+
*/
|
|
39
|
+
export const BundleEntryAbsence = z.enum(["no-content"]);
|
|
40
|
+
// One entry of the manifest: the identity a re-import needs, next to the relative path where the
|
|
41
|
+
// bytes sit in the zip. A folder carries no media type — it has no bytes.
|
|
42
|
+
export const BundleManifestEntry = z
|
|
43
|
+
.strictObject({
|
|
44
|
+
id: IntelId,
|
|
45
|
+
kind: BundleEntryKind,
|
|
46
|
+
title: z.string().min(1).max(240),
|
|
47
|
+
description: z.string().max(2_000).nullable(),
|
|
48
|
+
mediaType: z.string().min(1).max(160).nullable(),
|
|
49
|
+
// Relative to the zip root, forward slashes, no leading slash. Folders end with a slash so an
|
|
50
|
+
// empty folder still has an address. An entry with an `absence` keeps its path even though no
|
|
51
|
+
// file sits there: the path is what puts the node in the tree on the way back in.
|
|
52
|
+
path: z.string().min(1).max(4_000),
|
|
53
|
+
// ⚠️ OPTIONAL rather than nullable, and that is about files that already exist. This object is
|
|
54
|
+
// strict, so a required key would refuse every bundle written before #534 with
|
|
55
|
+
// `import_invalid_manifest` — a whole format broken over a word that only ever describes a node
|
|
56
|
+
// with nothing in it. Absent means the entry has its file, which is what every older bundle
|
|
57
|
+
// means.
|
|
58
|
+
absence: BundleEntryAbsence.optional(),
|
|
59
|
+
})
|
|
60
|
+
/**
|
|
61
|
+
* ⚠️ Only a table or an attachment may declare an absence, and the guard belongs HERE rather
|
|
62
|
+
* than at the import.
|
|
63
|
+
*
|
|
64
|
+
* A bundle is somebody else's file, and the import reads this word as permission to skip the
|
|
65
|
+
* check that a manifest entry has its file in the zip. Left unrestricted, an entry saying
|
|
66
|
+
* `kind: "document"` with `absence: "no-content"` would walk past that check even when the file
|
|
67
|
+
* IS in the zip — and the document would be created empty, silently, with nothing refused.
|
|
68
|
+
*
|
|
69
|
+
* The two kinds named here are the ones whose canonical content is the whole of them: a table
|
|
70
|
+
* IS its CSV and an attachment IS its bytes, so for them "no content" is a state of the node
|
|
71
|
+
* rather than a claim about a file. A document without a version is a different case and stays
|
|
72
|
+
* out — an empty markdown file says the same thing about it without ambiguity (#534, #560).
|
|
73
|
+
*
|
|
74
|
+
* Refusing at the boundary is the difference between a named refusal and lost content: the
|
|
75
|
+
* import validates this schema before it plans anything, so a manifest like that fails as
|
|
76
|
+
* `import_invalid_manifest` instead of importing something the bundle does not say.
|
|
77
|
+
*/
|
|
78
|
+
.refine((entry) => entry.absence === undefined || entry.kind === "table" || entry.kind === "attachment", {
|
|
79
|
+
message: "Only a table or attachment entry may declare an absence",
|
|
80
|
+
path: ["absence"],
|
|
81
|
+
});
|
|
82
|
+
/**
|
|
83
|
+
* What an export leaves out on purpose, named so a bundle says it rather than a reader guessing:
|
|
84
|
+
* version history, grants/shares, flow runs, and archived nodes are not in any bundle (#136).
|
|
85
|
+
*
|
|
86
|
+
* ⚠️ `unpublished-flow-changes` is the FIFTH, and it is the one exception to ADR-0006's own
|
|
87
|
+
* headline (#585). A bundle carries the current state of everything — except a flow that has been
|
|
88
|
+
* published, which travels as its PUBLISHED graph. Edits made after that publication are in no
|
|
89
|
+
* bundle, and they are not history: they are the newest state there is. The word exists because the
|
|
90
|
+
* loss is only acceptable while it is named, and `version-history` does not name it — a reader who
|
|
91
|
+
* saw only that word would expect the newest graph and get one that is deliberately older.
|
|
92
|
+
*
|
|
93
|
+
* ⚠️ These are WIRE values: an older reader refuses a bundle naming an exclusion it does not know,
|
|
94
|
+
* the same way it would refuse an unknown `kind`. The enum grows only for something an installation
|
|
95
|
+
* genuinely leaves behind, never as a place to note a nicety (ADR-0006, #433). Growing it costs the
|
|
96
|
+
* direction nobody migrates in — a bundle written HERE is refused by an installation older than
|
|
97
|
+
* this line, while every bundle written before it still parses, which is the direction 0.22.0's
|
|
98
|
+
* rebuild actually runs.
|
|
99
|
+
*/
|
|
100
|
+
export const BundleExclusion = z.enum([
|
|
101
|
+
"version-history",
|
|
102
|
+
"grants",
|
|
103
|
+
"flow-runs",
|
|
104
|
+
"archived-nodes",
|
|
105
|
+
"unpublished-flow-changes",
|
|
106
|
+
]);
|
|
107
|
+
export const BundleManifest = z.strictObject({
|
|
108
|
+
version: z.literal(1),
|
|
109
|
+
exportedAt: IsoDateTime,
|
|
110
|
+
// The node the export started at; `null` is the root of the tree — the whole installation as the
|
|
111
|
+
// exporting caller may read it.
|
|
112
|
+
rootId: IntelId.nullable(),
|
|
113
|
+
entries: z.array(BundleManifestEntry),
|
|
114
|
+
excluded: z.array(BundleExclusion),
|
|
115
|
+
});
|
|
116
|
+
// ── Bundle import (#137) ────────────────────────────────────────────────────────────────────────
|
|
117
|
+
/**
|
|
118
|
+
* What one import made. Import always creates new nodes — no merge, no overwrite, no restored IDs
|
|
119
|
+
* (#137, phase 1) — so the answer is counts and the new roots, never a diff. `replayed` marks the
|
|
120
|
+
* idempotent second answer to the same key: nothing was created twice.
|
|
121
|
+
*
|
|
122
|
+
* ⚠️ `excluded` is what the IMPORT knows about itself, never what the bundle claimed (ADR-0006,
|
|
123
|
+
* #433). A subtree moved between installations arrives with one version per node, no grants and no
|
|
124
|
+
* runs, and until now nothing said so at the moment somebody could still act on it — the word stood
|
|
125
|
+
* only in a `manifest.json` inside the zip that had already been written.
|
|
126
|
+
*
|
|
127
|
+
* It is deliberately NOT read back out of that manifest. A hand-written bundle saying `excluded: []`
|
|
128
|
+
* would then make the import report that nothing was left behind, and the import would launder
|
|
129
|
+
* somebody else's claim into an answer that sounds like its own — the trap `absence` is bound
|
|
130
|
+
* against in `BundleManifestEntry` above (#534, #560). The five exclusions hold for every import
|
|
131
|
+
* this build performs, with a manifest or from a naked folder, so this is a constant of the code.
|
|
132
|
+
*/
|
|
133
|
+
export const BundleImportResult = z.strictObject({
|
|
134
|
+
nodes: z.number().int().nonnegative(),
|
|
135
|
+
flows: z.number().int().nonnegative(),
|
|
136
|
+
rootNodeIds: z.array(IntelId),
|
|
137
|
+
replayed: z.boolean(),
|
|
138
|
+
excluded: z.array(BundleExclusion),
|
|
139
|
+
});
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const IntelId: z.ZodString;
|
|
3
|
+
export declare const IsoDateTime: z.ZodISODateTime;
|
|
4
|
+
export declare const IdempotencyKey: z.ZodString;
|
|
5
|
+
/**
|
|
6
|
+
* The short name a document or a published flow is offered under as a slash command (#775).
|
|
7
|
+
*
|
|
8
|
+
* ⚠️ One described primitive rather than the same sentence in two files, for the reason
|
|
9
|
+
* `IdempotencyKey` above gives: a document and a flow take the same kind of name out of the same
|
|
10
|
+
* catalogue, and a copy would be a second place for one sentence to drift. It sits here rather than
|
|
11
|
+
* in `node.ts` because `flow.ts` states it too, and this is the file both may read.
|
|
12
|
+
*
|
|
13
|
+
* ⚠️ The refusal spells the GRAMMAR, not the verdict. Zod's own `Invalid` tells a caller who sent
|
|
14
|
+
* `CRM Outreach` that something was wrong and not what would have worked, and the one thing they
|
|
15
|
+
* need is that the answer is `crm-outreach`.
|
|
16
|
+
*
|
|
17
|
+
* ⚠️ Uniqueness is NOT in this schema and cannot be: it is a question about the whole installation,
|
|
18
|
+
* across documents and flows at once, and it is answered where the write happens. A name another
|
|
19
|
+
* node or flow already holds is refused by name there, never quietly turned into a second one.
|
|
20
|
+
*/
|
|
21
|
+
export declare const PromptName: z.ZodString;
|
|
22
|
+
/**
|
|
23
|
+
* The version a write is made against, in the one form every writer of versioned content takes it.
|
|
24
|
+
*
|
|
25
|
+
* ⚠️ It lived beside the two node writers until #459 and moved here when the flow graph became the
|
|
26
|
+
* third — the point at which the repository stops copying and names the thing. It could not simply
|
|
27
|
+
* be imported: `flow.ts` may not depend on `node.ts` (the graph is `table → node`, `flow-run →
|
|
28
|
+
* flow`, and everything → here), and a copy would have been a second place for one sentence to
|
|
29
|
+
* drift, which is exactly what `IdempotencyKey` above exists to avoid.
|
|
30
|
+
*
|
|
31
|
+
* ⚠️ Nullable and required are not the same thing, and here they stand together (#437). `null` is
|
|
32
|
+
* how something that has no version yet is addressed, and it is the only way to write its first
|
|
33
|
+
* content; leaving the field out says nothing at all and is refused. Whoever leaves it out is
|
|
34
|
+
* almost always holding a node or a flow created one call earlier, and the plain type error they
|
|
35
|
+
* used to get — "expected string, received undefined" — reads as "this field must be an id", about
|
|
36
|
+
* a field that cannot have one yet. Both refusals therefore name both ways instead.
|
|
37
|
+
*
|
|
38
|
+
* ⚠️ It stays required once a version exists, and that is what it is for: a mismatch is answered
|
|
39
|
+
* with a `409` rather than by overwriting somebody else's newer version. Making it `optional()` to
|
|
40
|
+
* smooth the first write is the repair that breaks the guard — an absent field would then have to
|
|
41
|
+
* mean "there is none", and the forgetful caller silently replaces the newest one.
|
|
42
|
+
*
|
|
43
|
+
* ⚠️ The bounds remain `IntelId`'s. The repeated `min(1)` adds no rule — it only puts the sentence
|
|
44
|
+
* on the second value that gets tried after `undefined`, the empty string.
|
|
45
|
+
*
|
|
46
|
+
* ⚠️ The sentence says what the field TAKES, not what the caller did wrong. It answers a wrong type
|
|
47
|
+
* as well as an absent field, and "is required" would be false about the first — which would be
|
|
48
|
+
* this same ticket one corner further on. A value that is merely too long keeps Zod's own `Too
|
|
49
|
+
* big`: that one is already a true statement about what was sent.
|
|
50
|
+
*
|
|
51
|
+
* ⚠️ The JSON Schema it produces is the one `IntelId.nullable()` produced — an `anyOf` of the
|
|
52
|
+
* bounded string and `null`, still `required` — so nothing on the MCP surface moves when a field
|
|
53
|
+
* changes over to it.
|
|
54
|
+
*/
|
|
55
|
+
export declare function baseVersion(rule: string): z.ZodUnion<readonly [z.ZodString, z.ZodNull]>;
|
|
56
|
+
export declare const UI_LANGUAGES: readonly ["en", "de", "es"];
|
|
57
|
+
export type UiLanguage = (typeof UI_LANGUAGES)[number];
|
|
58
|
+
/**
|
|
59
|
+
* A set of things the reader is only partly entitled to see: the ones they may see BY NAME, the
|
|
60
|
+
* rest as a NUMBER (ADR-0004 §3). Never the titles of the rest, in any field, ever — a warning or a
|
|
61
|
+
* refusal must not become a way of reading the tree.
|
|
62
|
+
*
|
|
63
|
+
* ⚠️ It lives here rather than in `share.ts` because two domains state it: a grant says what it
|
|
64
|
+
* does not reach (`UnreadableNodes`), and a refusal says who is still calling in
|
|
65
|
+
* (`ProblemDetails.callers`, #448). `contract.ts` may not import from `share.ts` — the graph
|
|
66
|
+
* between these files has to stay acyclic — and a copy would be a second place for one rule to
|
|
67
|
+
* drift, which is what `IdempotencyKey` and `baseVersion` above exist against.
|
|
68
|
+
*/
|
|
69
|
+
export declare const NamedOrCounted: z.ZodObject<{
|
|
70
|
+
titles: z.ZodArray<z.ZodString>;
|
|
71
|
+
hidden: z.ZodNumber;
|
|
72
|
+
}, z.core.$strict>;
|
|
73
|
+
export type NamedOrCounted = z.infer<typeof NamedOrCounted>;
|
|
74
|
+
/**
|
|
75
|
+
* ⚠️ `callers` is the one member here that is not about every problem, and it is deliberate (#448).
|
|
76
|
+
* RFC 9457 allows extension members for exactly this: `folder_execute_in_use` refuses to narrow a
|
|
77
|
+
* library folder while flows from outside still call into it, and the CALLERS are the only thing
|
|
78
|
+
* that makes the refusal actionable. They used to exist only inside `detail` — an English sentence
|
|
79
|
+
* built on the server — so a German or Spanish surface could do nothing but print it verbatim, and
|
|
80
|
+
* no surface could shorten it or link the titles.
|
|
81
|
+
*
|
|
82
|
+
* The split is the point: the server decides WHAT is named and what is only counted, because that
|
|
83
|
+
* is an authorization answer nobody else can give; the surface decides how the sentence READS,
|
|
84
|
+
* because that is a language answer no server can give.
|
|
85
|
+
*
|
|
86
|
+
* `detail` keeps its sentence rather than emptying out — MCP hands a model prose and has nothing to
|
|
87
|
+
* formulate with, and an empty `detail` beside a new field would be the worst of the three states.
|
|
88
|
+
* It is absent on every other problem, so a reader must not treat its presence as guaranteed.
|
|
89
|
+
*/
|
|
90
|
+
export declare const ProblemDetails: z.ZodObject<{
|
|
91
|
+
type: z.ZodString;
|
|
92
|
+
status: z.ZodNumber;
|
|
93
|
+
title: z.ZodString;
|
|
94
|
+
detail: z.ZodOptional<z.ZodString>;
|
|
95
|
+
instance: z.ZodOptional<z.ZodString>;
|
|
96
|
+
code: z.ZodOptional<z.ZodString>;
|
|
97
|
+
callers: z.ZodOptional<z.ZodObject<{
|
|
98
|
+
titles: z.ZodArray<z.ZodString>;
|
|
99
|
+
hidden: z.ZodNumber;
|
|
100
|
+
}, z.core.$strict>>;
|
|
101
|
+
}, z.core.$strict>;
|
|
102
|
+
export type ProblemDetails = z.infer<typeof ProblemDetails>;
|
|
103
|
+
export declare const SessionUser: z.ZodObject<{
|
|
104
|
+
id: z.ZodString;
|
|
105
|
+
email: z.ZodEmail;
|
|
106
|
+
name: z.ZodNullable<z.ZodString>;
|
|
107
|
+
isAdmin: z.ZodBoolean;
|
|
108
|
+
}, z.core.$strict>;
|
|
109
|
+
export type SessionUser = z.infer<typeof SessionUser>;
|
|
110
|
+
export declare const LinkConfiguration: z.ZodObject<{
|
|
111
|
+
resourceId: z.ZodString;
|
|
112
|
+
}, z.core.$strict>;
|