wiki-viewer 1.14.1 → 1.14.2
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/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/api/agent/activity/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/events/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/files/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/fs/move/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/fs/search/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/internal/span/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/settings/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/sidecar/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/assets/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/share/[token]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/share/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/reveal/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/set-root/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/refresh/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/workspaces/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/upload/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/app/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/backlinks/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/content/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/download/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/file/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/folder/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/git-branches/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/git-checkout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/git-diff/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/git-file-info/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/git-history/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/git-pull/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/move/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/new-file/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/outlinks/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/page/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/presence/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/search/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/slugs/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/upload/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/watch/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +1 -1
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/.next/server/middleware-manifest.json +1 -1
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/package.json +1 -1
- package/bin/postbuild.js +21 -0
- package/package.json +1 -1
- package/.next/standalone/.github/workflows/publish.yml +0 -37
- package/.next/standalone/.handoffs/archive/handoff-20260612-113332.md +0 -98
- package/.next/standalone/.handoffs/archive/handoff-20260612-141032.md +0 -73
- package/.next/standalone/.pi/ownership.json +0 -3
- package/.next/standalone/AGENTS.md +0 -114
- package/.next/standalone/DESIGN.md +0 -521
- package/.next/standalone/README.md +0 -821
- package/.next/standalone/TODO.md +0 -20
- package/.next/standalone/agents/bootstrap-prompt.md +0 -14
- package/.next/standalone/agents/wiki-viewer-skill/SKILL.md +0 -456
- package/.next/standalone/bin/postbuild.js +0 -78
- package/.next/standalone/bin/wiki-viewer.js +0 -922
- package/.next/standalone/certificates/localhost-key.pem +0 -28
- package/.next/standalone/certificates/localhost.pem +0 -24
- package/.next/standalone/docs/agent-collab-plan.md +0 -1615
- package/.next/standalone/docs/agent-collab-v2-plan.md +0 -771
- package/.next/standalone/docs/agent-fs-plan.md +0 -232
- package/.next/standalone/docs/editorial-skin-spec.md +0 -242
- package/.next/standalone/docs/file-vs-collab-authority.md +0 -124
- package/.next/standalone/docs/mobile-readiness-spec.md +0 -229
- package/.next/standalone/docs/workspacing-plan.md +0 -364
- package/.next/standalone/packages/wiki-viewer-mcp/README.md +0 -195
- package/.next/standalone/packages/wiki-viewer-mcp/bench-e2e.mjs +0 -166
- package/.next/standalone/packages/wiki-viewer-mcp/bench-latency.mjs +0 -87
- package/.next/standalone/packages/wiki-viewer-mcp/bench-payload.mjs +0 -45
- package/.next/standalone/packages/wiki-viewer-mcp/dist/http-client.js +0 -331
- package/.next/standalone/packages/wiki-viewer-mcp/dist/index.js +0 -531
- package/.next/standalone/packages/wiki-viewer-mcp/dist/register.js +0 -94
- package/.next/standalone/packages/wiki-viewer-mcp/dist/state-cache.js +0 -28
- package/.next/standalone/packages/wiki-viewer-mcp/package-lock.json +0 -1716
- package/.next/standalone/packages/wiki-viewer-mcp/package.json +0 -41
- package/.next/standalone/packages/wiki-viewer-mcp/src/http-client.ts +0 -459
- package/.next/standalone/packages/wiki-viewer-mcp/src/index.ts +0 -638
- package/.next/standalone/packages/wiki-viewer-mcp/src/register.ts +0 -144
- package/.next/standalone/packages/wiki-viewer-mcp/src/state-cache.ts +0 -55
- package/.next/standalone/packages/wiki-viewer-mcp/tsconfig.json +0 -19
- package/.next/standalone/pnpm-lock.yaml +0 -6697
- package/.next/standalone/pnpm-workspace.yaml +0 -8
- package/.next/standalone/postcss.config.mjs +0 -2
- package/.next/standalone/src/app/api/agent/activity/route.ts +0 -59
- package/.next/standalone/src/app/api/agent/admin/agents/[agentId]/revoke/route.ts +0 -40
- package/.next/standalone/src/app/api/agent/admin/agents/route.ts +0 -33
- package/.next/standalone/src/app/api/agent/admin/registrations/[regId]/approve/route.ts +0 -83
- package/.next/standalone/src/app/api/agent/admin/registrations/[regId]/deny/route.ts +0 -36
- package/.next/standalone/src/app/api/agent/admin/registrations/route.ts +0 -27
- package/.next/standalone/src/app/api/agent/events/[...path]/route.ts +0 -148
- package/.next/standalone/src/app/api/agent/files/[...path]/route.ts +0 -219
- package/.next/standalone/src/app/api/agent/fs/file/[...path]/route.ts +0 -446
- package/.next/standalone/src/app/api/agent/fs/ls/[[...path]]/route.ts +0 -152
- package/.next/standalone/src/app/api/agent/fs/move/route.ts +0 -130
- package/.next/standalone/src/app/api/agent/fs/search/route.ts +0 -272
- package/.next/standalone/src/app/api/agent/internal/span/route.ts +0 -121
- package/.next/standalone/src/app/api/agent/register/[regId]/route.ts +0 -50
- package/.next/standalone/src/app/api/agent/register/route.ts +0 -118
- package/.next/standalone/src/app/api/agent/settings/route.ts +0 -34
- package/.next/standalone/src/app/api/agent/settings/token/regenerate/route.ts +0 -20
- package/.next/standalone/src/app/api/agent/sidecar/[...path]/route.ts +0 -53
- package/.next/standalone/src/app/api/agents/install/route.ts +0 -143
- package/.next/standalone/src/app/api/agents/skill/route.ts +0 -20
- package/.next/standalone/src/app/api/agents/skill.tar.gz/route.ts +0 -87
- package/.next/standalone/src/app/api/app-proxy/[...path]/route.ts +0 -247
- package/.next/standalone/src/app/api/assets/[...path]/route.ts +0 -75
- package/.next/standalone/src/app/api/auth/[...all]/route.ts +0 -7
- package/.next/standalone/src/app/api/owner/init/route.ts +0 -14
- package/.next/standalone/src/app/api/share/[token]/route.ts +0 -269
- package/.next/standalone/src/app/api/share/route.ts +0 -127
- package/.next/standalone/src/app/api/system/admins/route.ts +0 -103
- package/.next/standalone/src/app/api/system/auth-config/route.ts +0 -22
- package/.next/standalone/src/app/api/system/auth-settings/route.ts +0 -86
- package/.next/standalone/src/app/api/system/browse/route.ts +0 -82
- package/.next/standalone/src/app/api/system/clear-root/route.ts +0 -16
- package/.next/standalone/src/app/api/system/config/route.ts +0 -14
- package/.next/standalone/src/app/api/system/pins/route.ts +0 -38
- package/.next/standalone/src/app/api/system/reveal/route.ts +0 -36
- package/.next/standalone/src/app/api/system/root-status/route.ts +0 -13
- package/.next/standalone/src/app/api/system/set-root/route.ts +0 -53
- package/.next/standalone/src/app/api/system/users/route.ts +0 -120
- package/.next/standalone/src/app/api/system/workspaces/[id]/open/route.ts +0 -34
- package/.next/standalone/src/app/api/system/workspaces/[id]/refresh/route.ts +0 -32
- package/.next/standalone/src/app/api/system/workspaces/[id]/route.ts +0 -78
- package/.next/standalone/src/app/api/system/workspaces/route.ts +0 -128
- package/.next/standalone/src/app/api/upload/[...path]/route.ts +0 -85
- package/.next/standalone/src/app/api/wiki/app/route.ts +0 -60
- package/.next/standalone/src/app/api/wiki/backlinks/route.ts +0 -29
- package/.next/standalone/src/app/api/wiki/content/route.ts +0 -159
- package/.next/standalone/src/app/api/wiki/download/route.ts +0 -100
- package/.next/standalone/src/app/api/wiki/file/route.ts +0 -57
- package/.next/standalone/src/app/api/wiki/folder/route.ts +0 -34
- package/.next/standalone/src/app/api/wiki/git-branches/route.ts +0 -32
- package/.next/standalone/src/app/api/wiki/git-checkout/route.ts +0 -45
- package/.next/standalone/src/app/api/wiki/git-diff/route.ts +0 -33
- package/.next/standalone/src/app/api/wiki/git-file-info/route.ts +0 -27
- package/.next/standalone/src/app/api/wiki/git-history/route.ts +0 -27
- package/.next/standalone/src/app/api/wiki/git-pull/route.ts +0 -48
- package/.next/standalone/src/app/api/wiki/move/route.ts +0 -61
- package/.next/standalone/src/app/api/wiki/new-file/route.ts +0 -56
- package/.next/standalone/src/app/api/wiki/outlinks/route.ts +0 -76
- package/.next/standalone/src/app/api/wiki/page/route.ts +0 -92
- package/.next/standalone/src/app/api/wiki/presence/route.ts +0 -56
- package/.next/standalone/src/app/api/wiki/route.ts +0 -116
- package/.next/standalone/src/app/api/wiki/search/route.ts +0 -44
- package/.next/standalone/src/app/api/wiki/slugs/route.ts +0 -54
- package/.next/standalone/src/app/api/wiki/upload/route.ts +0 -95
- package/.next/standalone/src/app/api/wiki/watch/route.ts +0 -67
- package/.next/standalone/src/app/globals.css +0 -1249
- package/.next/standalone/src/app/icon.svg +0 -11
- package/.next/standalone/src/app/layout.tsx +0 -78
- package/.next/standalone/src/app/manifest.ts +0 -30
- package/.next/standalone/src/app/page.tsx +0 -3260
- package/.next/standalone/src/app/s/[token]/page.tsx +0 -357
- package/.next/standalone/src/app/signin/page.tsx +0 -16
- package/.next/standalone/src/app/signin/signin-form.tsx +0 -238
- package/.next/standalone/src/components/ai-panel/activity-row.tsx +0 -284
- package/.next/standalone/src/components/ai-panel/ai-panel.tsx +0 -311
- package/.next/standalone/src/components/ai-panel/token-section.tsx +0 -313
- package/.next/standalone/src/components/auth-settings-sheet.tsx +0 -474
- package/.next/standalone/src/components/confirm-dialog.tsx +0 -56
- package/.next/standalone/src/components/dir-picker.tsx +0 -606
- package/.next/standalone/src/components/editor/backlinks-panel.tsx +0 -139
- package/.next/standalone/src/components/editor/bubble-menu.tsx +0 -346
- package/.next/standalone/src/components/editor/callout-extension.ts +0 -36
- package/.next/standalone/src/components/editor/comment-pip.tsx +0 -56
- package/.next/standalone/src/components/editor/comment-thread.tsx +0 -254
- package/.next/standalone/src/components/editor/csv-viewer.tsx +0 -379
- package/.next/standalone/src/components/editor/document-outline.tsx +0 -230
- package/.next/standalone/src/components/editor/editor-toolbar.tsx +0 -564
- package/.next/standalone/src/components/editor/editor.tsx +0 -1327
- package/.next/standalone/src/components/editor/extensions/drag-handle.ts +0 -325
- package/.next/standalone/src/components/editor/extensions/heading-anchors.ts +0 -55
- package/.next/standalone/src/components/editor/extensions/proof-span.ts +0 -60
- package/.next/standalone/src/components/editor/extensions/resizable-image.tsx +0 -159
- package/.next/standalone/src/components/editor/extensions.ts +0 -150
- package/.next/standalone/src/components/editor/file-fallback-viewer.tsx +0 -75
- package/.next/standalone/src/components/editor/folder-index.tsx +0 -236
- package/.next/standalone/src/components/editor/google-doc-viewer.tsx +0 -73
- package/.next/standalone/src/components/editor/image-viewer.tsx +0 -57
- package/.next/standalone/src/components/editor/large-file-gate.tsx +0 -108
- package/.next/standalone/src/components/editor/link-popover.tsx +0 -111
- package/.next/standalone/src/components/editor/media-popover.tsx +0 -212
- package/.next/standalone/src/components/editor/media-viewer.tsx +0 -70
- package/.next/standalone/src/components/editor/mermaid-viewer.tsx +0 -286
- package/.next/standalone/src/components/editor/node-app-viewer.tsx +0 -328
- package/.next/standalone/src/components/editor/notebook-viewer.tsx +0 -371
- package/.next/standalone/src/components/editor/office/docx-viewer.tsx +0 -93
- package/.next/standalone/src/components/editor/office/office-chrome.tsx +0 -83
- package/.next/standalone/src/components/editor/office/pptx-viewer.tsx +0 -104
- package/.next/standalone/src/components/editor/office/xlsx-viewer.tsx +0 -192
- package/.next/standalone/src/components/editor/pdf-viewer.tsx +0 -32
- package/.next/standalone/src/components/editor/proof-span-popover.tsx +0 -162
- package/.next/standalone/src/components/editor/slash-commands.tsx +0 -629
- package/.next/standalone/src/components/editor/source-viewer.tsx +0 -289
- package/.next/standalone/src/components/editor/suggest-edit-popover.tsx +0 -229
- package/.next/standalone/src/components/editor/suggestion-card.tsx +0 -206
- package/.next/standalone/src/components/editor/table-menu.tsx +0 -232
- package/.next/standalone/src/components/editor/view-mode-comment-button.tsx +0 -77
- package/.next/standalone/src/components/editor/website-viewer.tsx +0 -75
- package/.next/standalone/src/components/editor/wiki-link-create-dialog.tsx +0 -189
- package/.next/standalone/src/components/editor/wiki-link-decorator.ts +0 -79
- package/.next/standalone/src/components/editor/wiki-link-extension.ts +0 -120
- package/.next/standalone/src/components/editor/wiki-link-picker.tsx +0 -250
- package/.next/standalone/src/components/layout/viewer-toolbar.tsx +0 -54
- package/.next/standalone/src/components/search/search-command-dialog.tsx +0 -246
- package/.next/standalone/src/components/search/sidebar-search-box.tsx +0 -121
- package/.next/standalone/src/components/search/snippet-text.tsx +0 -48
- package/.next/standalone/src/components/share-dialog.tsx +0 -307
- package/.next/standalone/src/components/theme-provider.tsx +0 -16
- package/.next/standalone/src/components/theme-toggle.tsx +0 -24
- package/.next/standalone/src/components/ui/badge.tsx +0 -35
- package/.next/standalone/src/components/ui/button.tsx +0 -56
- package/.next/standalone/src/components/ui/card.tsx +0 -63
- package/.next/standalone/src/components/ui/collapsible.tsx +0 -9
- package/.next/standalone/src/components/ui/command.tsx +0 -151
- package/.next/standalone/src/components/ui/context-menu.tsx +0 -191
- package/.next/standalone/src/components/ui/dialog.tsx +0 -119
- package/.next/standalone/src/components/ui/dropdown-menu.tsx +0 -194
- package/.next/standalone/src/components/ui/input.tsx +0 -22
- package/.next/standalone/src/components/ui/label.tsx +0 -25
- package/.next/standalone/src/components/ui/popover.tsx +0 -33
- package/.next/standalone/src/components/ui/scroll-area.tsx +0 -47
- package/.next/standalone/src/components/ui/select.tsx +0 -156
- package/.next/standalone/src/components/ui/separator.tsx +0 -30
- package/.next/standalone/src/components/ui/sheet.tsx +0 -140
- package/.next/standalone/src/components/ui/skeleton.tsx +0 -15
- package/.next/standalone/src/components/ui/switch.tsx +0 -28
- package/.next/standalone/src/components/ui/tabs.tsx +0 -54
- package/.next/standalone/src/components/ui/textarea.tsx +0 -21
- package/.next/standalone/src/components/ui/tip.tsx +0 -23
- package/.next/standalone/src/components/ui/toggle-group.tsx +0 -41
- package/.next/standalone/src/components/ui/tooltip.tsx +0 -27
- package/.next/standalone/src/components/view-width-toggle.tsx +0 -70
- package/.next/standalone/src/components/wiki/frontmatter-header.tsx +0 -164
- package/.next/standalone/src/hooks/use-is-mobile.ts +0 -14
- package/.next/standalone/src/lib/app-runner.ts +0 -272
- package/.next/standalone/src/lib/auth/admin.ts +0 -120
- package/.next/standalone/src/lib/auth/allowlist.ts +0 -50
- package/.next/standalone/src/lib/auth/client.ts +0 -4
- package/.next/standalone/src/lib/auth/csrf.ts +0 -68
- package/.next/standalone/src/lib/auth/server.ts +0 -215
- package/.next/standalone/src/lib/cabinets/tree.ts +0 -75
- package/.next/standalone/src/lib/config.ts +0 -114
- package/.next/standalone/src/lib/embeds/detect.ts +0 -142
- package/.next/standalone/src/lib/git-secrets.ts +0 -65
- package/.next/standalone/src/lib/git.ts +0 -503
- package/.next/standalone/src/lib/google/detect.ts +0 -107
- package/.next/standalone/src/lib/markdown/parse-frontmatter.ts +0 -104
- package/.next/standalone/src/lib/markdown/remark-wikilinks.ts +0 -100
- package/.next/standalone/src/lib/markdown/sanitize-schema.ts +0 -106
- package/.next/standalone/src/lib/markdown/to-html.ts +0 -282
- package/.next/standalone/src/lib/markdown/to-markdown.ts +0 -252
- package/.next/standalone/src/lib/proof/activity-shared.ts +0 -31
- package/.next/standalone/src/lib/proof/activity.ts +0 -74
- package/.next/standalone/src/lib/proof/audit.ts +0 -88
- package/.next/standalone/src/lib/proof/auth.ts +0 -143
- package/.next/standalone/src/lib/proof/block-refs.ts +0 -133
- package/.next/standalone/src/lib/proof/blocks.ts +0 -73
- package/.next/standalone/src/lib/proof/client-auth.ts +0 -23
- package/.next/standalone/src/lib/proof/collab-state.ts +0 -81
- package/.next/standalone/src/lib/proof/event-bus.ts +0 -47
- package/.next/standalone/src/lib/proof/file-lock.ts +0 -43
- package/.next/standalone/src/lib/proof/glob.ts +0 -51
- package/.next/standalone/src/lib/proof/idempotency.ts +0 -37
- package/.next/standalone/src/lib/proof/lease.ts +0 -117
- package/.next/standalone/src/lib/proof/mutex.ts +0 -36
- package/.next/standalone/src/lib/proof/ops-applier.ts +0 -727
- package/.next/standalone/src/lib/proof/owner-auth.ts +0 -2
- package/.next/standalone/src/lib/proof/pending.ts +0 -97
- package/.next/standalone/src/lib/proof/proof-span.ts +0 -141
- package/.next/standalone/src/lib/proof/rate-limit.ts +0 -53
- package/.next/standalone/src/lib/proof/raw-fs.ts +0 -197
- package/.next/standalone/src/lib/proof/register-rate-limit.ts +0 -53
- package/.next/standalone/src/lib/proof/registry.ts +0 -195
- package/.next/standalone/src/lib/proof/sidecar.ts +0 -103
- package/.next/standalone/src/lib/proof/suggest-capture.ts +0 -69
- package/.next/standalone/src/lib/proof/types.ts +0 -182
- package/.next/standalone/src/lib/proof-config.ts +0 -14
- package/.next/standalone/src/lib/root-dir.ts +0 -35
- package/.next/standalone/src/lib/search/indexable-exts.ts +0 -25
- package/.next/standalone/src/lib/search/indexer.ts +0 -634
- package/.next/standalone/src/lib/search/sanitize.ts +0 -35
- package/.next/standalone/src/lib/search/search-db.ts +0 -57
- package/.next/standalone/src/lib/search/watcher-pool.ts +0 -79
- package/.next/standalone/src/lib/shared-docs/db.ts +0 -177
- package/.next/standalone/src/lib/toast.ts +0 -9
- package/.next/standalone/src/lib/utils.ts +0 -6
- package/.next/standalone/src/lib/wiki-helpers.ts +0 -36
- package/.next/standalone/src/lib/workspace-client.ts +0 -82
- package/.next/standalone/src/lib/workspace-context.ts +0 -173
- package/.next/standalone/src/lib/workspaces.ts +0 -400
- package/.next/standalone/src/middleware.ts +0 -44
- package/.next/standalone/src/stores/ai-panel-store.ts +0 -79
- package/.next/standalone/src/stores/editor-store.ts +0 -439
- package/.next/standalone/src/stores/pin-store.ts +0 -56
- package/.next/standalone/src/stores/proof-store.ts +0 -124
- package/.next/standalone/src/stores/recent-store.ts +0 -51
- package/.next/standalone/src/stores/search-store.ts +0 -104
- package/.next/standalone/src/stores/show-hidden-store.ts +0 -26
- package/.next/standalone/src/stores/sidebar-width-store.ts +0 -39
- package/.next/standalone/src/stores/skin-store.ts +0 -42
- package/.next/standalone/src/stores/tree-store.ts +0 -52
- package/.next/standalone/src/stores/view-width-store.ts +0 -101
- package/.next/standalone/src/stores/wiki-slugs-store.ts +0 -75
- package/.next/standalone/src/tests/proof/activity-aggregator.test.ts +0 -146
- package/.next/standalone/src/tests/proof/admin-create-user.test.ts +0 -43
- package/.next/standalone/src/tests/proof/agent-fs.test.ts +0 -973
- package/.next/standalone/src/tests/proof/agent-ownership.test.ts +0 -140
- package/.next/standalone/src/tests/proof/agent-workspace-scope.test.ts +0 -134
- package/.next/standalone/src/tests/proof/agents-install.test.ts +0 -110
- package/.next/standalone/src/tests/proof/bench-write.ts +0 -179
- package/.next/standalone/src/tests/proof/better-auth.test.ts +0 -68
- package/.next/standalone/src/tests/proof/block-refs.test.ts +0 -108
- package/.next/standalone/src/tests/proof/blocks.test.ts +0 -92
- package/.next/standalone/src/tests/proof/collab-state.test.ts +0 -501
- package/.next/standalone/src/tests/proof/comments-ops.test.ts +0 -177
- package/.next/standalone/src/tests/proof/editor-roundtrip.test.ts +0 -85
- package/.next/standalone/src/tests/proof/external-edit.test.ts +0 -58
- package/.next/standalone/src/tests/proof/file-lock.test.ts +0 -80
- package/.next/standalone/src/tests/proof/git-branches-checkout.test.ts +0 -136
- package/.next/standalone/src/tests/proof/git-read-features.test.ts +0 -473
- package/.next/standalone/src/tests/proof/git-secrets.test.ts +0 -138
- package/.next/standalone/src/tests/proof/git-sparse.test.ts +0 -257
- package/.next/standalone/src/tests/proof/git-workspace.test.ts +0 -135
- package/.next/standalone/src/tests/proof/git.test.ts +0 -243
- package/.next/standalone/src/tests/proof/glob.test.ts +0 -82
- package/.next/standalone/src/tests/proof/helpers/auth-session.ts +0 -27
- package/.next/standalone/src/tests/proof/markdown-to-html.test.ts +0 -46
- package/.next/standalone/src/tests/proof/ops-applier.test.ts +0 -368
- package/.next/standalone/src/tests/proof/owner-init.test.ts +0 -2
- package/.next/standalone/src/tests/proof/parse-frontmatter.test.ts +0 -60
- package/.next/standalone/src/tests/proof/preload.ts +0 -21
- package/.next/standalone/src/tests/proof/proof-span.test.ts +0 -98
- package/.next/standalone/src/tests/proof/rate-limit.test.ts +0 -54
- package/.next/standalone/src/tests/proof/readonly-enforcement.test.ts +0 -161
- package/.next/standalone/src/tests/proof/reconcile-sidecar.test.ts +0 -195
- package/.next/standalone/src/tests/proof/registration-flow.test.ts +0 -330
- package/.next/standalone/src/tests/proof/registry.test.ts +0 -169
- package/.next/standalone/src/tests/proof/routes.test.ts +0 -516
- package/.next/standalone/src/tests/proof/search-index.test.ts +0 -376
- package/.next/standalone/src/tests/proof/sidecar-lifecycle.test.ts +0 -177
- package/.next/standalone/src/tests/proof/sidecar-trim.test.ts +0 -58
- package/.next/standalone/src/tests/proof/suggestion-ops.test.ts +0 -280
- package/.next/standalone/src/tests/proof/wiki-content-put.test.ts +0 -140
- package/.next/standalone/src/tests/proof/wiki-routes-auth.test.ts +0 -208
- package/.next/standalone/src/tests/proof/workspace-isolation.test.ts +0 -87
- package/.next/standalone/src/tests/proof/workspaces-api.test.ts +0 -227
- package/.next/standalone/src/types/index.ts +0 -47
- package/.next/standalone/tailwind.config.ts +0 -191
- package/.next/standalone/tsconfig.json +0 -41
- package/.next/standalone/tsconfig.tsbuildinfo +0 -1
- /package/.next/standalone/.next/static/{WMOTgfV82apmdovxzgbMx → rRyvFORvJoc5OWbCR2A_P}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{WMOTgfV82apmdovxzgbMx → rRyvFORvJoc5OWbCR2A_P}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{WMOTgfV82apmdovxzgbMx → rRyvFORvJoc5OWbCR2A_P}/_ssgManifest.js +0 -0
|
@@ -1,330 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* End-to-end TOFU registration flow tests.
|
|
3
|
-
*
|
|
4
|
-
* Tests: POST register → poll (pending) → admin approve → poll (token pickup, one-shot) → 410 consumed
|
|
5
|
-
* POST register → admin deny → poll 410 denied
|
|
6
|
-
*/
|
|
7
|
-
import { test, before, after, beforeEach } from "node:test";
|
|
8
|
-
import assert from "node:assert/strict";
|
|
9
|
-
import { mkdtemp, rm } from "node:fs/promises";
|
|
10
|
-
import { tmpdir } from "node:os";
|
|
11
|
-
import path from "node:path";
|
|
12
|
-
|
|
13
|
-
let tmpHome: string;
|
|
14
|
-
|
|
15
|
-
before(async () => {
|
|
16
|
-
tmpHome = await mkdtemp(path.join(tmpdir(), "wiki-reg-flow-test-"));
|
|
17
|
-
process.env.HOME = tmpHome;
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
after(async () => {
|
|
21
|
-
await rm(tmpHome, { recursive: true, force: true });
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
// Import routes after HOME is set (disk reads are lazy)
|
|
25
|
-
import { POST as registerPOST } from "../../app/api/agent/register/route.js";
|
|
26
|
-
import { GET as pollGET } from "../../app/api/agent/register/[regId]/route.js";
|
|
27
|
-
import { POST as approvePOST } from "../../app/api/agent/admin/registrations/[regId]/approve/route.js";
|
|
28
|
-
import { POST as denyPOST } from "../../app/api/agent/admin/registrations/[regId]/deny/route.js";
|
|
29
|
-
import { GET as listPendingGET } from "../../app/api/agent/admin/registrations/route.js";
|
|
30
|
-
import { ensureRegistry } from "../../lib/proof/registry.js";
|
|
31
|
-
import { makeUserSession } from "./helpers/auth-session.js";
|
|
32
|
-
|
|
33
|
-
async function getOwnerHeaders(): Promise<Record<string, string>> {
|
|
34
|
-
await ensureRegistry();
|
|
35
|
-
const cookies = await makeUserSession();
|
|
36
|
-
return { Cookie: cookies };
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function makeRegisterReq(body: Record<string, unknown>): Request {
|
|
40
|
-
// Auto-fill required fields unless explicitly overridden
|
|
41
|
-
const payload: Record<string, unknown> = {
|
|
42
|
-
displayName: "Test Agent",
|
|
43
|
-
scope: { paths: ["**/*"], ops: ["read", "mutate"] },
|
|
44
|
-
...body,
|
|
45
|
-
};
|
|
46
|
-
return new Request("http://localhost:3000/api/agent/register", {
|
|
47
|
-
method: "POST",
|
|
48
|
-
headers: { "Content-Type": "application/json" },
|
|
49
|
-
body: JSON.stringify(payload),
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
beforeEach(async () => {
|
|
54
|
-
// Reset rate-limit buckets before each test
|
|
55
|
-
const { _resetRegisterBuckets } = await import("../../lib/proof/register-rate-limit");
|
|
56
|
-
_resetRegisterBuckets();
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
function makePollReq(regId: string): Request {
|
|
60
|
-
return new Request(`http://localhost:3000/api/agent/register/${regId}`);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function makeApproveReq(regId: string, extraHeaders: Record<string, string>): Request {
|
|
64
|
-
return new Request(`http://localhost:3000/api/agent/admin/registrations/${regId}/approve`, {
|
|
65
|
-
method: "POST",
|
|
66
|
-
headers: { "Content-Type": "application/json", ...extraHeaders },
|
|
67
|
-
body: "{}",
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function makeDenyReq(regId: string, extraHeaders: Record<string, string>): Request {
|
|
72
|
-
return new Request(`http://localhost:3000/api/agent/admin/registrations/${regId}/deny`, {
|
|
73
|
-
method: "POST",
|
|
74
|
-
headers: extraHeaders,
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function makeListReq(extraHeaders: Record<string, string>): Request {
|
|
79
|
-
return new Request("http://localhost:3000/api/agent/admin/registrations", {
|
|
80
|
-
headers: extraHeaders,
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// ── Register → approve → pickup → replay consumed ─────────────────────────────
|
|
85
|
-
|
|
86
|
-
test("POST /register returns 202 with registrationId", async () => {
|
|
87
|
-
const res = await registerPOST(makeRegisterReq({ id: "ai:flow-test-a", displayName: "Flow A" }));
|
|
88
|
-
assert.equal(res.status, 202);
|
|
89
|
-
const body = (await res.json()) as { registrationId: string; pollUrl: string; status: string };
|
|
90
|
-
assert.equal(body.status, "pending");
|
|
91
|
-
assert.ok(body.registrationId.startsWith("reg_"));
|
|
92
|
-
assert.ok(body.pollUrl.includes(body.registrationId));
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
test("GET /register/:regId returns 202 status:pending before approval", async () => {
|
|
96
|
-
const regRes = await registerPOST(makeRegisterReq({ id: "ai:flow-test-b" }));
|
|
97
|
-
const { registrationId } = (await regRes.json()) as { registrationId: string };
|
|
98
|
-
const pollRes = await pollGET(makePollReq(registrationId), {
|
|
99
|
-
params: Promise.resolve({ regId: registrationId }),
|
|
100
|
-
});
|
|
101
|
-
assert.equal(pollRes.status, 202);
|
|
102
|
-
const body = (await pollRes.json()) as { status: string };
|
|
103
|
-
assert.equal(body.status, "pending");
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
test("Full flow: register → list pending → approve → poll pickup → 410 on replay", async () => {
|
|
107
|
-
const ownerH = await getOwnerHeaders();
|
|
108
|
-
|
|
109
|
-
// 1. Register
|
|
110
|
-
const regRes = await registerPOST(makeRegisterReq({ id: "ai:flow-approve" }));
|
|
111
|
-
const { registrationId } = (await regRes.json()) as { registrationId: string };
|
|
112
|
-
|
|
113
|
-
// 2. List pending — should appear
|
|
114
|
-
const listRes = await listPendingGET(makeListReq(ownerH));
|
|
115
|
-
assert.equal(listRes.status, 200);
|
|
116
|
-
const { pending } = (await listRes.json()) as { pending: Array<{ registrationId: string }> };
|
|
117
|
-
assert.ok(pending.some((r) => r.registrationId === registrationId));
|
|
118
|
-
|
|
119
|
-
// 3. Approve
|
|
120
|
-
const approveRes = await approvePOST(makeApproveReq(registrationId, ownerH), {
|
|
121
|
-
params: Promise.resolve({ regId: registrationId }),
|
|
122
|
-
});
|
|
123
|
-
assert.equal(approveRes.status, 200);
|
|
124
|
-
const approveBody = (await approveRes.json()) as { ok: boolean; agentId: string };
|
|
125
|
-
assert.equal(approveBody.ok, true);
|
|
126
|
-
assert.equal(approveBody.agentId, "ai:flow-approve");
|
|
127
|
-
|
|
128
|
-
// 4. Poll — should get token (status: approved)
|
|
129
|
-
const pollRes1 = await pollGET(makePollReq(registrationId), {
|
|
130
|
-
params: Promise.resolve({ regId: registrationId }),
|
|
131
|
-
});
|
|
132
|
-
assert.equal(pollRes1.status, 200);
|
|
133
|
-
const pollBody1 = (await pollRes1.json()) as { status: string; token: string; agentId: string };
|
|
134
|
-
assert.equal(pollBody1.status, "approved");
|
|
135
|
-
assert.ok(typeof pollBody1.token === "string" && pollBody1.token.length > 0);
|
|
136
|
-
assert.equal(pollBody1.agentId, "ai:flow-approve");
|
|
137
|
-
|
|
138
|
-
// 5. Poll again — token consumed, 410
|
|
139
|
-
const pollRes2 = await pollGET(makePollReq(registrationId), {
|
|
140
|
-
params: Promise.resolve({ regId: registrationId }),
|
|
141
|
-
});
|
|
142
|
-
assert.equal(pollRes2.status, 410);
|
|
143
|
-
const pollBody2 = (await pollRes2.json()) as { status: string };
|
|
144
|
-
assert.equal(pollBody2.status, "consumed");
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
// ── Register → deny → poll 410 ────────────────────────────────────────────────
|
|
148
|
-
|
|
149
|
-
test("Denied registration: register → deny → poll returns 410 denied", async () => {
|
|
150
|
-
const ownerH = await getOwnerHeaders();
|
|
151
|
-
|
|
152
|
-
const regRes = await registerPOST(makeRegisterReq({ id: "ai:flow-deny" }));
|
|
153
|
-
const { registrationId } = (await regRes.json()) as { registrationId: string };
|
|
154
|
-
|
|
155
|
-
const denyRes = await denyPOST(makeDenyReq(registrationId, ownerH), {
|
|
156
|
-
params: Promise.resolve({ regId: registrationId }),
|
|
157
|
-
});
|
|
158
|
-
assert.equal(denyRes.status, 200);
|
|
159
|
-
|
|
160
|
-
const pollRes = await pollGET(makePollReq(registrationId), {
|
|
161
|
-
params: Promise.resolve({ regId: registrationId }),
|
|
162
|
-
});
|
|
163
|
-
assert.equal(pollRes.status, 410);
|
|
164
|
-
const body = (await pollRes.json()) as { status: string };
|
|
165
|
-
assert.equal(body.status, "denied");
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
// ── Validation errors ─────────────────────────────────────────────────────────
|
|
169
|
-
|
|
170
|
-
test("POST /register with invalid id returns 400", async () => {
|
|
171
|
-
const res = await registerPOST(makeRegisterReq({ id: "invalid-id" }));
|
|
172
|
-
assert.equal(res.status, 400);
|
|
173
|
-
const body = (await res.json()) as { error: string };
|
|
174
|
-
assert.equal(body.error, "INVALID_PAYLOAD");
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
test("POST /register with missing id returns 400", async () => {
|
|
178
|
-
const res = await registerPOST(makeRegisterReq({ displayName: "No ID" }));
|
|
179
|
-
assert.equal(res.status, 400);
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
test("GET /register unknown regId returns 404", async () => {
|
|
183
|
-
const res = await pollGET(makePollReq("reg_doesnotexist"), {
|
|
184
|
-
params: Promise.resolve({ regId: "reg_doesnotexist" }),
|
|
185
|
-
});
|
|
186
|
-
assert.equal(res.status, 404);
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
test("POST approve without owner cookie returns 401", async () => {
|
|
190
|
-
const regRes = await registerPOST(makeRegisterReq({ id: "ai:flow-noauth" }));
|
|
191
|
-
const { registrationId } = (await regRes.json()) as { registrationId: string };
|
|
192
|
-
const res = await approvePOST(makeApproveReq(registrationId, {}), {
|
|
193
|
-
params: Promise.resolve({ regId: registrationId }),
|
|
194
|
-
});
|
|
195
|
-
assert.equal(res.status, 401);
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
test("POST deny without owner cookie returns 401", async () => {
|
|
199
|
-
const regRes = await registerPOST(makeRegisterReq({ id: "ai:flow-nodenyauth" }));
|
|
200
|
-
const { registrationId } = (await regRes.json()) as { registrationId: string };
|
|
201
|
-
const res = await denyPOST(makeDenyReq(registrationId, {}), {
|
|
202
|
-
params: Promise.resolve({ regId: registrationId }),
|
|
203
|
-
});
|
|
204
|
-
assert.equal(res.status, 401);
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
test("POST approve already-approved registration returns 409", async () => {
|
|
208
|
-
const ownerH = await getOwnerHeaders();
|
|
209
|
-
|
|
210
|
-
const regRes = await registerPOST(makeRegisterReq({ id: "ai:flow-double-approve" }));
|
|
211
|
-
const { registrationId } = (await regRes.json()) as { registrationId: string };
|
|
212
|
-
|
|
213
|
-
await approvePOST(makeApproveReq(registrationId, ownerH), {
|
|
214
|
-
params: Promise.resolve({ regId: registrationId }),
|
|
215
|
-
});
|
|
216
|
-
const res = await approvePOST(makeApproveReq(registrationId, ownerH), {
|
|
217
|
-
params: Promise.resolve({ regId: registrationId }),
|
|
218
|
-
});
|
|
219
|
-
assert.equal(res.status, 409);
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
// ── Oracle fix #1: registrationId entropy ────────────────────────────────────
|
|
223
|
-
|
|
224
|
-
test("POST /register: registrationId has 128-bit entropy (reg_<32hex>)", async () => {
|
|
225
|
-
const res = await registerPOST(
|
|
226
|
-
makeRegisterReq({ id: "ai:entropy-test", displayName: "Entropy", scope: { paths: ["**/*"], ops: ["read"] } }),
|
|
227
|
-
);
|
|
228
|
-
assert.equal(res.status, 202);
|
|
229
|
-
const body = (await res.json()) as { registrationId: string };
|
|
230
|
-
assert.match(body.registrationId, /^reg_[0-9a-f]{32}$/);
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
// ── Oracle fix #3: register input validation ──────────────────────────────────
|
|
234
|
-
|
|
235
|
-
test("POST /register: displayName too long returns 400", async () => {
|
|
236
|
-
const res = await registerPOST(
|
|
237
|
-
makeRegisterReq({
|
|
238
|
-
id: "ai:validation-a",
|
|
239
|
-
displayName: "x".repeat(81),
|
|
240
|
-
scope: { paths: ["**/*"], ops: ["read"] },
|
|
241
|
-
}),
|
|
242
|
-
);
|
|
243
|
-
assert.equal(res.status, 400);
|
|
244
|
-
const body = (await res.json()) as { error: string };
|
|
245
|
-
assert.equal(body.error, "INVALID_PAYLOAD");
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
test("POST /register: scope.paths empty returns 400", async () => {
|
|
249
|
-
const res = await registerPOST(
|
|
250
|
-
makeRegisterReq({
|
|
251
|
-
id: "ai:validation-b",
|
|
252
|
-
displayName: "Test",
|
|
253
|
-
scope: { paths: [], ops: ["read"] },
|
|
254
|
-
}),
|
|
255
|
-
);
|
|
256
|
-
assert.equal(res.status, 400);
|
|
257
|
-
const body = (await res.json()) as { error: string };
|
|
258
|
-
assert.equal(body.error, "INVALID_PAYLOAD");
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
test("POST /register: scope.ops invalid value returns 400", async () => {
|
|
262
|
-
const res = await registerPOST(
|
|
263
|
-
makeRegisterReq({
|
|
264
|
-
id: "ai:validation-c",
|
|
265
|
-
displayName: "Test",
|
|
266
|
-
scope: { paths: ["**/*"], ops: ["read", "destroy"] },
|
|
267
|
-
}),
|
|
268
|
-
);
|
|
269
|
-
assert.equal(res.status, 400);
|
|
270
|
-
const body = (await res.json()) as { error: string };
|
|
271
|
-
assert.equal(body.error, "INVALID_PAYLOAD");
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
test("POST /register: missing scope returns 400", async () => {
|
|
275
|
-
// Build a request that explicitly omits scope (bypass makeRegisterReq defaults)
|
|
276
|
-
const req = new Request("http://localhost:3000/api/agent/register", {
|
|
277
|
-
method: "POST",
|
|
278
|
-
headers: { "Content-Type": "application/json" },
|
|
279
|
-
body: JSON.stringify({ id: "ai:validation-d", displayName: "Test" }),
|
|
280
|
-
});
|
|
281
|
-
const res = await registerPOST(req);
|
|
282
|
-
assert.equal(res.status, 400);
|
|
283
|
-
const body = (await res.json()) as { error: string };
|
|
284
|
-
assert.equal(body.error, "INVALID_PAYLOAD");
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
test("POST /register: 11th rapid attempt returns 429", async () => {
|
|
288
|
-
const { _resetRegisterBuckets } = await import("../../lib/proof/register-rate-limit.js");
|
|
289
|
-
_resetRegisterBuckets();
|
|
290
|
-
|
|
291
|
-
const makeReq = (n: number) =>
|
|
292
|
-
makeRegisterReq({
|
|
293
|
-
id: `ai:rate-reg-${n}`,
|
|
294
|
-
displayName: `Rate ${n}`,
|
|
295
|
-
scope: { paths: ["**/*"], ops: ["read"] },
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
// Consume all 10 tokens
|
|
299
|
-
for (let i = 0; i < 10; i++) {
|
|
300
|
-
const res = await registerPOST(makeReq(i));
|
|
301
|
-
assert.ok(res.status !== 429, `Attempt ${i} should not be rate-limited`);
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
// 11th should be 429
|
|
305
|
-
const res = await registerPOST(makeReq(10));
|
|
306
|
-
assert.equal(res.status, 429);
|
|
307
|
-
const body = (await res.json()) as { error: string };
|
|
308
|
-
assert.equal(body.error, "RATE_LIMITED");
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
test("POST approve with custom scope stores custom scope", async () => {
|
|
312
|
-
const ownerH = await getOwnerHeaders();
|
|
313
|
-
|
|
314
|
-
const regRes = await registerPOST(makeRegisterReq({ id: "ai:flow-scope" }));
|
|
315
|
-
const { registrationId } = (await regRes.json()) as { registrationId: string };
|
|
316
|
-
|
|
317
|
-
const customScope = { paths: ["notes/**"], ops: ["read"] };
|
|
318
|
-
const approveRes = await approvePOST(
|
|
319
|
-
new Request(
|
|
320
|
-
`http://localhost:3000/api/agent/admin/registrations/${registrationId}/approve`,
|
|
321
|
-
{
|
|
322
|
-
method: "POST",
|
|
323
|
-
headers: { "Content-Type": "application/json", ...ownerH },
|
|
324
|
-
body: JSON.stringify({ scope: customScope }),
|
|
325
|
-
},
|
|
326
|
-
),
|
|
327
|
-
{ params: Promise.resolve({ regId: registrationId }) },
|
|
328
|
-
);
|
|
329
|
-
assert.equal(approveRes.status, 200);
|
|
330
|
-
});
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
import { test, before, after } from "node:test";
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
import { mkdtemp, rm } from "node:fs/promises";
|
|
4
|
-
import { tmpdir } from "node:os";
|
|
5
|
-
import path from "node:path";
|
|
6
|
-
import { createHash, randomBytes } from "node:crypto";
|
|
7
|
-
|
|
8
|
-
let tmpHome: string;
|
|
9
|
-
|
|
10
|
-
before(async () => {
|
|
11
|
-
tmpHome = await mkdtemp(path.join(tmpdir(), "wiki-registry-test-"));
|
|
12
|
-
process.env.HOME = tmpHome;
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
after(async () => {
|
|
16
|
-
await rm(tmpHome, { recursive: true, force: true });
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
import {
|
|
20
|
-
ensureRegistry,
|
|
21
|
-
readRegistry,
|
|
22
|
-
writeRegistry,
|
|
23
|
-
hashToken,
|
|
24
|
-
lookupAgentByToken,
|
|
25
|
-
lookupAgentById,
|
|
26
|
-
addAgent,
|
|
27
|
-
removeAgent,
|
|
28
|
-
updateLastSeen,
|
|
29
|
-
} from "../../lib/proof/registry.js";
|
|
30
|
-
import type { Agent } from "../../lib/proof/registry.js";
|
|
31
|
-
|
|
32
|
-
function makeAgent(id: string, tokenHash: string): Agent {
|
|
33
|
-
return {
|
|
34
|
-
id,
|
|
35
|
-
displayName: id,
|
|
36
|
-
tokenHash,
|
|
37
|
-
scope: { paths: ["**/*"], ops: ["read", "mutate"] },
|
|
38
|
-
createdAt: new Date().toISOString(),
|
|
39
|
-
lastSeen: new Date().toISOString(),
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// ── ensureRegistry ────────────────────────────────────────────────────────────
|
|
44
|
-
|
|
45
|
-
test("ensureRegistry creates registry when absent", async () => {
|
|
46
|
-
const r = await ensureRegistry();
|
|
47
|
-
assert.equal(r.version, 1);
|
|
48
|
-
assert.ok(Array.isArray(r.agents));
|
|
49
|
-
assert.equal(r.agents.length, 0);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
test("ensureRegistry is idempotent — returns same registry on second call", async () => {
|
|
53
|
-
const r1 = await ensureRegistry();
|
|
54
|
-
const r2 = await ensureRegistry();
|
|
55
|
-
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
// ── readRegistry / writeRegistry roundtrip ────────────────────────────────────
|
|
59
|
-
|
|
60
|
-
test("readRegistry returns null when file absent after rm", async () => {
|
|
61
|
-
// ensureRegistry has been called, file exists. This test writes a new
|
|
62
|
-
// modified registry and reads it back — not testing absent case again.
|
|
63
|
-
const r = await readRegistry();
|
|
64
|
-
assert.ok(r !== null, "registry should exist");
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
test("writeRegistry / readRegistry roundtrip preserves agents", async () => {
|
|
68
|
-
const token = randomBytes(16).toString("hex");
|
|
69
|
-
const hash = hashToken(token);
|
|
70
|
-
const r = await ensureRegistry();
|
|
71
|
-
r.agents.push(makeAgent("ai:roundtrip", hash));
|
|
72
|
-
await writeRegistry(r);
|
|
73
|
-
const r2 = await readRegistry();
|
|
74
|
-
assert.ok(r2);
|
|
75
|
-
assert.ok(r2.agents.some((a) => a.id === "ai:roundtrip"));
|
|
76
|
-
assert.equal(r2.agents.find((a) => a.id === "ai:roundtrip")!.tokenHash, hash);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
// ── hashToken ─────────────────────────────────────────────────────────────────
|
|
80
|
-
|
|
81
|
-
test("hashToken returns sha256 hex of input", () => {
|
|
82
|
-
const input = "hello-world";
|
|
83
|
-
const expected = createHash("sha256").update(input, "utf8").digest("hex");
|
|
84
|
-
assert.equal(hashToken(input), expected);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
test("hashToken is deterministic", () => {
|
|
88
|
-
const h1 = hashToken("abc");
|
|
89
|
-
const h2 = hashToken("abc");
|
|
90
|
-
assert.equal(h1, h2);
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
// ── lookupAgentByToken ────────────────────────────────────────────────────────
|
|
94
|
-
|
|
95
|
-
test("lookupAgentByToken returns agent for correct token", async () => {
|
|
96
|
-
const token = randomBytes(16).toString("hex");
|
|
97
|
-
const hash = hashToken(token);
|
|
98
|
-
await addAgent(makeAgent("ai:lookup-test", hash));
|
|
99
|
-
const found = await lookupAgentByToken(token);
|
|
100
|
-
assert.ok(found);
|
|
101
|
-
assert.equal(found.id, "ai:lookup-test");
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
test("lookupAgentByToken returns null for wrong token", async () => {
|
|
105
|
-
const found = await lookupAgentByToken("totally-wrong-token");
|
|
106
|
-
assert.equal(found, null);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
// ── lookupAgentById ───────────────────────────────────────────────────────────
|
|
110
|
-
|
|
111
|
-
test("lookupAgentById returns agent by id", async () => {
|
|
112
|
-
const token = randomBytes(16).toString("hex");
|
|
113
|
-
await addAgent(makeAgent("ai:byid-test", hashToken(token)));
|
|
114
|
-
const found = await lookupAgentById("ai:byid-test");
|
|
115
|
-
assert.ok(found);
|
|
116
|
-
assert.equal(found.id, "ai:byid-test");
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
test("lookupAgentById returns null for unknown id", async () => {
|
|
120
|
-
const found = await lookupAgentById("ai:nonexistent");
|
|
121
|
-
assert.equal(found, null);
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
// ── addAgent / removeAgent ────────────────────────────────────────────────────
|
|
125
|
-
|
|
126
|
-
test("addAgent adds agent to registry", async () => {
|
|
127
|
-
const token = randomBytes(16).toString("hex");
|
|
128
|
-
await addAgent(makeAgent("ai:add-test", hashToken(token)));
|
|
129
|
-
const r = await readRegistry();
|
|
130
|
-
assert.ok(r?.agents.some((a) => a.id === "ai:add-test"));
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
test("addAgent replaces existing agent with same id", async () => {
|
|
134
|
-
const t1 = randomBytes(16).toString("hex");
|
|
135
|
-
const t2 = randomBytes(16).toString("hex");
|
|
136
|
-
await addAgent(makeAgent("ai:replace-test", hashToken(t1)));
|
|
137
|
-
await addAgent(makeAgent("ai:replace-test", hashToken(t2)));
|
|
138
|
-
const r = await readRegistry();
|
|
139
|
-
const found = r?.agents.filter((a) => a.id === "ai:replace-test");
|
|
140
|
-
assert.equal(found?.length, 1);
|
|
141
|
-
assert.equal(found?.[0].tokenHash, hashToken(t2));
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
test("removeAgent removes agent and returns true", async () => {
|
|
145
|
-
const token = randomBytes(16).toString("hex");
|
|
146
|
-
await addAgent(makeAgent("ai:remove-test", hashToken(token)));
|
|
147
|
-
const removed = await removeAgent("ai:remove-test");
|
|
148
|
-
assert.equal(removed, true);
|
|
149
|
-
const found = await lookupAgentById("ai:remove-test");
|
|
150
|
-
assert.equal(found, null);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
test("removeAgent returns false for unknown id", async () => {
|
|
154
|
-
const removed = await removeAgent("ai:no-such-agent");
|
|
155
|
-
assert.equal(removed, false);
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
// ── updateLastSeen ────────────────────────────────────────────────────────────
|
|
159
|
-
|
|
160
|
-
test("updateLastSeen updates lastSeen timestamp", async () => {
|
|
161
|
-
const token = randomBytes(16).toString("hex");
|
|
162
|
-
const agent = makeAgent("ai:lastseen-test", hashToken(token));
|
|
163
|
-
agent.lastSeen = "2020-01-01T00:00:00.000Z";
|
|
164
|
-
await addAgent(agent);
|
|
165
|
-
await updateLastSeen("ai:lastseen-test");
|
|
166
|
-
const found = await lookupAgentById("ai:lastseen-test");
|
|
167
|
-
assert.ok(found);
|
|
168
|
-
assert.notEqual(found.lastSeen, "2020-01-01T00:00:00.000Z");
|
|
169
|
-
});
|