.github/9
ISSUE_TEMPLATE/3bug_report.md config.yml feature_request.md
workflows/3ci.yml clean-clone.yml release.yml
CODEOWNERS dependabot.yml pull_request_template.md
apps/630
api/250
src/243
common/30
__tests__/3authorize.test.ts bigint-serialization.interceptor.test.ts files-limits.test.ts
filters/1all-exceptions.filter.ts
guards/3auth.guard.ts internal-service.guard.ts rate-limit.guard.ts
interceptors/2actor-context.interceptor.ts bigint-serialization.interceptor.ts
middleware/2idempotency.test.ts idempotency.ts
pipes/1zod-validation.pipe.ts
actor-context.ts audit.service.ts cache.test.ts cache.ts cookies.ts core.module.ts deprecation.ts email.service.ts errors.ts event-bus.ts log-scrubber.test.ts log-scrubber.ts logger.ts permission-cache-bridge.ts prisma.service.ts redis.service.ts trace-metadata.ts types.ts
config/1env.ts
lib/11
__tests__/5crypto.test.ts filter-builder.test.ts jwt.test.ts pagination.test.ts positions.test.ts
authorize.ts crypto.ts filter-builder.ts jwt.ts pagination.ts positions.ts
modules/197
ai/28
__tests__/4ai-writing.test.ts database-ai.test.ts generate-executor.test.ts prompts.test.ts
generator/4executor.ts generate.controller.ts generate.dto.ts generate.service.ts
ai-chat.service.ts ai-rate-limit.ts ai-writing.controller.ts ai-writing.dto.ts ai-writing.service.ts ai.controller.ts ai.module.ts ai.service.ts budget-guard.service.ts database-ai.controller.ts database-ai.dto.ts database-ai.service.ts db-prompts.ts dto.ts gateway-provider.ts ledger.service.ts prompts.ts rag.controller.ts rag.dto.ts rag.service.ts
api-keys/3api-keys.controller.ts api-keys.module.ts api-keys.service.ts
audit/2audit-log.controller.ts audit.module.ts
auth/4auth.controller.ts auth.module.ts auth.service.ts dto.ts
automations/5automations.controller.ts automations.module.ts automations.service.ts dto.ts webhook-incoming.controller.ts
blocks/5
__tests__/1batch-version-cas.test.ts
block.service.ts blocks.controller.ts blocks.module.ts dto.ts
comments/4comments.controller.ts comments.module.ts comments.service.ts dto.ts
databases/9
__tests__/3normalize-select-options.test.ts option-id-canonicalization.test.ts record-open-query-shape.test.ts
database.service.ts databases.controller.ts databases.module.ts dto.ts property-cache-schema.ts query.service.ts
docs/2docs.controller.ts docs.module.ts
files/10
__tests__/1quota.test.ts
dto.ts files.controller.ts files.module.ts files.service.ts quota.ts record.ts s3.ts uploads.controller.ts uploads.service.ts
forms/18debug.controller.ts form.dto.ts forms.controller.ts forms.module.ts forms.service.ts markdown.test.ts markdown.ts optional-auth.guard.ts public-forms.controller.ts public-forms.service.ts question.dto.ts questions.service.ts rate-limit.ts recaptcha.ts slug.ts submissions.controller.ts submissions.service.ts submit-schema.ts
health/3health.controller.ts health.module.ts health.service.ts
integrations/3integrations.controller.ts integrations.module.ts integrations.service.ts
internal/12
__tests__/2flush-query-shape.test.ts internal.endpoints.test.ts
ai-test-seam.controller.ts ai-test-seam.dto.ts ai-test-seam.service.ts internal.controller.ts internal.dto.ts internal.module.ts internal.service.ts test-seam.controller.ts test-seam.dto.ts test-seam.service.ts
notifications/3notifications.controller.ts notifications.module.ts notifications.service.ts
oauth/6
__tests__/1oauth.scopes.test.ts
oauth.controller.ts oauth.module.ts oauth.service.ts scopes.ts token-keys.ts
org/15audit.service.ts embed-preview.controller.ts guards.ts members.service.ts org-admin.controller.ts org-policy.service.ts org.module.ts overview.service.ts policy-effective.controller.ts policy.schema.ts policy.test.ts retention.service.ts totp.test.ts totp.ts two-factor.service.ts
orgs/5dto.ts orgs.controller.ts orgs.module.ts orgs.service.ts util.ts
pages/4dto.ts page.service.ts pages.controller.ts pages.module.ts
scim/15
__tests__/3email-mapping.test.ts etag.test.ts filters.test.ts
etag.ts filters.ts groups.service.ts schemas.ts scim-admin.controller.ts scim-admin.service.ts scim-auth.guard.ts scim-auth.service.ts scim-errors.ts scim.controller.ts scim.module.ts users.service.ts
search/4
__tests__/1search.service.test.ts
search.controller.ts search.module.ts search.service.ts
sessions/3sessions.controller.ts sessions.module.ts sessions.service.ts
share/3share.controller.ts share.module.ts share.service.ts
sso/16
__tests__/4enforcement.test.ts oidc.verify.test.ts provisioning.test.ts saml.validate.test.ts
enforcement.ts oidc.controller.ts oidc.service.ts oidc.ts provisioning.service.ts saml.controller.ts saml.ts schemas.ts sso-admin.controller.ts sso-admin.service.ts sso-secrets.ts sso.module.ts
teams/4dto.ts teams.controller.ts teams.module.ts teams.service.ts
users/4dto.ts users.controller.ts users.module.ts users.service.ts
webhooks/3webhooks.controller.ts webhooks.module.ts webhooks.service.ts
workspaces/4dto.ts workspaces.controller.ts workspaces.module.ts workspaces.service.ts
types/1xmldom.d.ts
app.module.ts constants.ts main.ts
_probe_rawbody.cjs .env.example Dockerfile package.json README.md tsconfig.json vitest.config.ts
realtime/33
src/17auth.ts comments.ts config.ts event-source.ts http-store.ts index.ts metrics.ts notifications.ts page-updated-source.ts presence.ts prisma-store.ts protocol.ts rate-limit.ts room-key.ts rooms.ts server.ts update-log.ts
test/11auth.test.ts config.test.ts event-source.test.ts http-store.test.ts metrics-merge.test.ts page-updated-source.test.ts presence.test.ts protocol.test.ts rate-limit.test.ts rooms.test.ts task-0094-builders.test.ts
.env.example Dockerfile package.json README.md tsconfig.json
web/255
src/244
app/45
__tests__/1theme-tokens.test.ts
(app)/26
w/25
[workspace]/25
ask/1page.tsx
databases/1
[id]/1page.tsx
favorites/1page.tsx
files/1page.tsx
notifications/1page.tsx
page/4
[id]/4
[block]/1page.tsx
share/1page.tsx
layout.tsx page.tsx
search/1page.tsx
settings/10
appearance/1page.tsx
automations/3
[id]/1page.tsx
new/1page.tsx
page.tsx
billing/1page.tsx
developers/1page.tsx
members/1page.tsx
permissions/1page.tsx
teams/1page.tsx
page.tsx
shared/1page.tsx
templates/1page.tsx
trash/1page.tsx
layout.tsx page.tsx
layout.tsx
(auth)/4
login/1page.tsx
register/1page.tsx
reset-password/1page.tsx
layout.tsx
api/2
metrics/1route.ts
v1/1
health/1route.ts
f/1
[slug]/1page.tsx
health/1
ready/1route.ts
org/2
[orgId]/2
admin/2
integrations/1page.tsx
page.tsx
share/1
[id]/1page.tsx
error.tsx global-error.tsx globals.css layout.tsx not-found.tsx page.tsx providers.tsx
components/118
admin/10
org-admin/8ApiKeysTab.tsx AuditTab.tsx MembersTab.tsx OverviewTab.tsx PoliciesTab.tsx RetentionTab.tsx WebhooksTab.tsx WorkspacePicker.tsx
ScimCard.tsx SsoTabs.tsx
ai/6ai-panel.tsx ask-ai-submenu.tsx db-ai-dialog.tsx generate-page-dialog.tsx writing-actions-menu.tsx writing-diff.tsx
automations/5action-editor.tsx condition-editor.tsx lib.ts run-history.tsx trigger-editor.tsx
collaboration/6CursorLayer.tsx OfflineBanner.tsx PresenceBar.tsx README.md ReviewFailedDialog.tsx StatusChip.tsx
comments/3comment-panel.tsx comment-thread.tsx mention-input.tsx
database/27
__tests__/2cell-editor.test.tsx cell-renderer.test.tsx
AiExtractDialog.tsx AiFormulaDialog.tsx AiGenerateDialog.tsx board-view.tsx buttons-panel.tsx calendar-view.tsx cell-editor.tsx cell-renderer.tsx chart-view.tsx database-page-view.tsx database-toolbar.tsx database-view-renderer.tsx db-embedded.tsx filter-builder.tsx form-builder-view.tsx formula-editor.tsx gallery-view.tsx group-builder.tsx list-view.tsx property-editor.tsx record-header.tsx record-panel.tsx sort-builder.tsx table-view.tsx timeline-view.tsx
dialogs/7
__tests__/1move-to-dialog.test.tsx
create-dialog.tsx dialog.tsx file-permissions-dialog.tsx invite-dialog.tsx move-to-dialog.tsx share-dialog.tsx
editor/19
__tests__/3code-block-text.test.ts code-block.test.tsx expandable.test.tsx
block-card.tsx block-renderer.tsx block-save-queue.ts block-toolbar.tsx context-menu.tsx expandable.tsx history-popover.tsx inline-editor.tsx insert-dialog.tsx page-canvas.tsx page-spinner.tsx page-view.tsx selection-toolbar.tsx slash-menu.tsx template-dialog.tsx type-menu.tsx
files/4FileBlock.tsx FileBrowser.tsx FilePicker.tsx PreviewModal.tsx
form/4form-field.tsx form-renderer.tsx form-responses-view.tsx form-view.tsx
layout/8
__tests__/1page-tree-icon.test.tsx
command-palette.tsx factory-logo.tsx page-tree-node.tsx sidebar.tsx theme-provider.tsx topbar.tsx workspace-shell.tsx
mentions/3
__tests__/1mention-model.test.ts
mention-model.ts MentionPopup.tsx
search/3ask-ai-search.tsx results-list.tsx search-dialog.tsx
settings/10
api-keys/4ApiKeyCreateDialog.tsx ApiKeyRevealDialog.tsx ApiKeyTable.tsx ScopesBadge.tsx
webhooks/5CurlExamples.tsx DeliveryInspector.tsx EventExplorer.tsx OverviewTab.tsx WebhooksTab.tsx
settings-shell.tsx
ui/3confirm-dialog.tsx form.tsx toaster.tsx
hooks/21
__tests__/4realtime-frame-handler.test.ts use-blocks.test.ts use-database-options.test.ts use-workspace.test.tsx
realtime-frame-handler.ts use-ai-stream.ts use-auth.ts use-blocks.ts use-database.ts use-db-ai-stream.ts use-forms.ts use-members.ts use-mention-sources.ts use-notifications.ts use-offline-status.ts use-pages.ts use-presence-announcer.ts use-presence-toasts.ts use-presence.ts use-realtime.ts use-workspace.ts
lib/50
__tests__/21ai-database.test.ts ai-generate.test.ts ai-sse.test.ts ai-writing.test.ts api-keys.test.ts api-members.test.ts auth-refresh.test.ts auth-store.test.ts batch-queue-drop.test.ts block-content.test.ts clipboard-import.test.ts code-highlight.test.ts offline-status.test.ts presence-announcer.test.ts presence-color.test.ts presence-cursor.test.ts presence-emitter.test.ts realtime-url.test.ts search.test.ts utils.test.ts writing-diff.test.ts
files/7
__tests__/2picker.test.ts upload.test.ts
api.ts picker.ts upload-store.ts upload.ts use-file-uploads.ts
ai-database.ts ai.ts api-keys.ts api.ts auth-store.ts batch-queue.ts block-content.ts clipboard-import.ts code-highlight.ts constants.ts offline-status.ts org-admin.ts presence-announcer.ts presence-color.ts presence-cursor.ts presence-editor-views.ts presence-emitter.ts query-client.ts realtime.ts search.ts types.ts utils.ts
stores/8
__tests__/1block-patch-store.test.ts
block-patch-store.ts comment-pill-store.ts database-store.ts editor-store.ts offlineQueue.ts presence-store.ts ui-store.ts
instrumentation.ts middleware.ts
.env.example Dockerfile next-env.d.ts next.config.mjs package.json postcss.config.mjs README.md tailwind.config.ts tsconfig.json tsconfig.tsbuildinfo vitest.config.ts
worker/92
src/87
__tests__/13ai-embedding.test.ts ai-request.test.ts ai-usage-budget.test.ts audit-export.test.ts email-decision.test.ts encrypt.test.ts health-search-index-lag.test.ts mime.test.ts retention.test.ts s3-sign.test.ts search-index.test.ts smtp.test.ts webhook-sign.test.ts
health/1server.ts
lib/12
__tests__/1clamav.test.ts
clamav.ts encrypt.ts job-otel.ts mime.ts notify.ts prisma.ts redis-stream.ts redis.ts s3.ts sharp.ts smtp.ts
processors/56
automations/28
__tests__/3condition-evaluator.spec.ts executors.spec.ts run-pipeline.spec.ts
executors/17assign-user.ts call-integration.ts change-status.ts classify.ts create-notification.ts create-page.ts email-cap.ts helpers.ts integration-registry.ts permission.ts record-write.ts registry.ts run-ai-action.ts send-email.ts send-webhook.ts types.ts update-record.ts
condition-evaluator.ts dead-letter.ts log.ts matcher.ts pipeline.ts run-state.ts schedule.ts watchdog.ts
files/15
__tests__/4errors.test.ts scan-gate.test.ts status.test.ts temp.test.ts
steps/4finalize.ts metadata.ts scan.ts thumbnails.ts
cleanup.ts errors.ts generateThumbs.ts processor.ts status.ts temp.ts types.ts
search-index/4builders.ts grants.ts index.ts processor.ts
ai-embedding.ts ai.processor.ts audit-export.ts automations.processor.ts email-decision.processor.ts email.processor.ts maintenance.processor.ts retention.ts webhooks.processor.ts
config.ts events.ts index.ts logger.ts queues.ts
.env.example Dockerfile package.json README.md tsconfig.json
docs/73
api/17ai.md authentication.md automations.md blocks.md comments.md databases.md files.md forms.md openapi.yaml org-admin.md pages.md scim.md search.md sso.md versioning.md webhooks.md workspaces.md
architecture/10ai-architecture.md automation.md backend-architecture.md database-architecture.md frontend-architecture.md realtime-architecture.md search-architecture.md security-architecture.md storage.md system-architecture.md
database/2database-architecture.md redis-keys.md
development/8admin-guide.md coding-standards.md deployment.md development-guide.md files-pipeline.md perf-report.md performance.md testing.md
product/4functional-requirements.md non-functional-requirements.md product-requirements.md ux-requirements.md
requirements/1requirements-matrix.md
security/5audit-report.md files.md forms.md license-allowlist.md security-architecture.md
tasks/16phase-00-foundation.md phase-01-authentication.md phase-02-workspace.md phase-03-pages.md phase-04-editor.md phase-05-databases.md phase-06-relations.md phase-07-collaboration.md phase-08-search.md phase-09-files.md phase-10-forms.md phase-11-automation.md phase-12-ai.md phase-13-api.md phase-14-enterprise.md phase-15-production.md
ui/9ai.md automations.md design-system.md developers.md files.md forms.md org-admin.md scim.md sso.md
support-matrix.md
infrastructure/71
caddy/1Caddyfile
docker/6
init/101-extensions.sql
opensearch/1init-indices.json
.env.docker docker-compose.yml opensearch-init.sh README.md
kubernetes/40
observability/20
alertmanager/1alertmanager.yaml
grafana/8
dashboards/6ai.json api-overview.json infra.json realtime.json search.json workers-queues.json
provisioning/2
dashboards/1dashboards.yaml
datasources/1datasource.yaml
prometheus/3alerts.yaml recording-rules.yaml scrape.yaml
scripts/1sync-sources.mjs
alertmanager.yaml grafana.yaml kustomization.yaml namespace.yaml node-exporter.yaml otel-collector.yaml prometheus.yaml
postgres/7configmap.yaml cronjob-backup.yaml cronjob-opensearch-snapshot.yaml pgbouncer.yaml replica.yaml statefulset.yaml walg-iam-policy.yaml
api.yaml configmap.yaml ingress.yaml kustomization.yaml namespace.yaml networkpolicy.yaml pdb.yaml README.md realtime.yaml redis.yaml secret.example.yaml web.yaml worker.yaml
nginx/2nginx.conf README.md
observability/14
alertmanager/1alertmanager.yaml
grafana/8
dashboards/6ai.json api-overview.json infra.json realtime.json search.json workers-queues.json
provisioning/2
dashboards/1dashboards.yaml
datasources/1datasource.yaml
prometheus/3alerts.yaml recording-rules.yaml scrape.yaml
scripts/1dashboard-completeness.mjs
README.md
terraform/8compute.tf data.tf main.tf network.tf outputs.tf README.md security.tf variables.tf
packages/289
ai/24
src/20
providers/7anthropic.ts google.ts http.ts index.ts openai-compatible.ts rag.test.ts writing.test.ts
schemas/2database.ts generate.ts
adapters.test.ts config.test.ts config.ts gateway.test.ts gateway.ts index.ts tools.test.ts tools.ts types.ts usage.test.ts usage.ts
package.json README.md tsconfig.json vitest.config.ts
auth/11
src/7index.ts passwords.test.ts passwords.ts sessions.test.ts sessions.ts tokens.test.ts tokens.ts
package.json README.md tsconfig.json vitest.config.ts
collaboration/17
src/13awareness.ts codec.test.ts codec.ts index.ts lww.test.ts lww.ts mapping.ts offline.ts outbox.test.ts outbox.ts provider.test.ts provider.ts types.ts
package.json README.md tsconfig.json vitest.config.ts
config/7
src/4eslint.base.js index.ts prettier.base.json tsconfig.base.json
package.json README.md tsconfig.json
database-client/5
src/2index.test.ts index.ts
package.json README.md tsconfig.json
database-engine/33
src/29
filter/2filter.test.ts index.ts
formula/8evaluator.ts formula.test.ts functions.ts index.ts lexer.ts parser.ts types.ts validate.ts
query/6group.ts index.ts paginate.ts pivot.ts query.test.ts sort.ts
relations/2index.ts relations.test.ts
rollups/2index.ts rollups.test.ts
values/5dates.ts index.ts registry.ts types.ts values.test.ts
views/3buttons.ts index.ts views.test.ts
index.ts
package.json README.md tsconfig.json vitest.config.ts
editor/25
src/21
marks/1highlight.ts
nodes/2equation.ts mention.ts
autosave.test.ts autosave.ts clipboard.test.ts clipboard.ts codec.test.ts codec.ts context-menu.test.ts context-menu.ts diff.test.ts diff.ts factory.ts history.test.ts history.ts index.ts positions.ts slash.test.ts slash.ts types.ts
package.json README.md tsconfig.json vitest.config.ts
observability/20
src/16
__tests__/8db-redis-metrics.test.ts metrics.test.ts otel.test.ts pino-otel.test.ts prometheus.test.ts resource.test.ts scrubber.test.ts traceparent.test.ts
index.ts metrics.ts otel.ts pino-otel.ts prometheus.ts resource.ts scrubber.ts traceparent.ts
package.json README.md tsconfig.json vitest.config.ts
permissions/11
src/7index.ts levels.test.ts levels.ts resolve.test.ts resolve.ts rules.test.ts rules.ts
package.json README.md tsconfig.json vitest.config.ts
search/22
src/18chunking.test.ts chunking.ts client.test.ts client.ts embeddings.test.ts embeddings.ts hybrid.test.ts hybrid.ts index.ts indexer.test.ts indexer.ts mapping.test.ts mapping.ts queries.test.ts queries.ts rrf.test.ts rrf.ts types.ts
package.json README.md tsconfig.json vitest.config.ts
shared/61
src/57
dto/17ai.dto.ts auth.dto.test.ts auth.dto.ts block.dto.ts browser-safety.test.ts comment.dto.ts database.dto.test.ts database.dto.ts file.dto.ts formula-ast.ts index.ts notification.dto.ts page.dto.ts search.dto.ts share.dto.ts webhook.dto.ts workspace.dto.ts
events/8audit-catalog.test.ts audit-catalog.ts audit-csv.test.ts audit-csv.ts audit-scope.test.ts audit-scope.ts catalog.test.ts catalog.ts
realtime/6comment-events.ts frames.test.ts frames.ts notification-policy.ts notification-prefs.ts task-0094.test.ts
automation.test.ts automation.ts constants.ts crypto.test.ts crypto.ts env.ts errors.ts events.test.ts events.ts forms.test.ts forms.ts index.ts markdown.test.ts markdown.ts mentions.test.ts mentions.ts net.test.ts net.ts positions.test.ts positions.ts presence.test.ts presence.ts security-headers.ts webhook-delivery.test.ts webhook-delivery.ts webhook-events.ts
package.json README.md tsconfig.json vitest.config.ts
storage/16
src/12client.test.ts client.ts index.ts keys.test.ts keys.ts mime.test.ts mime.ts presign.test.ts presign.ts thumbnails.test.ts thumbnails.ts types.ts
package.json README.md tsconfig.json vitest.config.ts
ui/37
src/33
components/19avatar.tsx badge.tsx button.tsx checkbox.tsx command.tsx context-menu.tsx dialog.tsx dropdown-menu.tsx empty-state.tsx index.ts popover.tsx separator.tsx skeleton.tsx slider.tsx spinner.tsx switch.tsx tabs.tsx toast.tsx tooltip.tsx
color.ts command-filter.test.ts command-filter.ts focus.test.ts focus.ts formatters.test.ts formatters.ts index.ts theme.test.ts theme.ts toast-store.test.ts toast-store.ts tokens.test.ts tokens.ts
package.json README.md tsconfig.json vitest.config.ts
prisma/16
migrations/13
20260927000000_init/1migration.sql
20260928000000_search_documents_content_hash/1migration.sql
20260929000000_workspace_usage_storage_bytes/1migration.sql
20260930000000_form_submitted_notification_type/1migration.sql
20261001000000_ai_phase12/1migration.sql
20261002000000_webhooks_secret_encrypted_dlq/1migration.sql
20261002111436_webhook_delivery_latency/1migration.sql
20261002120000_org_admin_2fa_retention_unique/1migration.sql
20261002215124_audit_export/1migration.sql
20261003210000_perf_indexes_hot_paths/1migration.sql
20261004004500_perf_indexes_hot_paths_2/1migration.sql
migration_lock.toml README.md
schema.prisma seed.ts verify.ts
scripts/7backup-health.ts docs-completeness.mjs generate-openapi.mjs minio-init.ts opensearch-reindex.ts storage-orphans.ts verify-clean-clone.sh
tests/169
e2e/63
.auth/1user.json
fixtures/7
files/6clip.mp4 clip.wav clip.webm hero-1400.png note.docx note.txt
realtime.ts
mocks/2oidc-issuer.ts saml-idp.ts
playwright-report/3
data/2a6557bae9c2714a658968d4eb8534195c08ebda8.png e3092d07d00a16063e46385c02a559a9054fa847.webm
index.html
reports/1files-security.json
specs/34ai-database.spec.ts ai-generate.spec.ts ai-rag.spec.ts ai-security.spec.ts ai-writing.spec.ts ai.spec.ts api-keys.spec.ts appearance-theme.spec.ts auth.spec.ts automation.spec.ts collab-two-tab.spec.ts comments.spec.ts databases.spec.ts default-workspace-alias.spec.ts developers.spec.ts editor.spec.ts files.spec.ts final-flow.spec.ts forms.spec.ts oauth.spec.ts org-admin.spec.ts pages.spec.ts performance.spec.ts presence-cursors.spec.ts qa-paste-toggle.spec.ts realtime.spec.ts scim.spec.ts search-index-lag.spec.ts search.spec.ts sharing.spec.ts sso.spec.ts task-0094-comments-notifications.spec.ts webhooks.spec.ts workspace.spec.ts
test-results-final-flow/3
final-flow-Release-v1-0-fi-6c06b-w-state-carries-sequential--chromium-desktop/2test-failed-1.png trace.zip
.last-run.json
utils/4api.ts dnd.ts search-lag.ts wait.ts
.gitignore fixtures.ts global-setup.ts package.json playwright.config.ts playwright.final-flow.config.ts README.md tsconfig.json
fixtures/1
files/1make-sparse.ts
integration/60
ai-capability/2ai-app.capability.test.ts gateway.capability.test.ts
drill/2seed-drill.mjs verify-restore.mjs
fixtures/5
files/5clip.mp4 clip.wav doc.pdf hero-1400.png note.txt
helpers/3api.ts containers.ts seed.ts
realtime/11control-channel.test.ts convergence.test.ts flush-rebase-http.test.ts handshake.test.ts heartbeat-limits.test.ts lifecycle.test.ts presence.test.ts rebase.test.ts resume.test.ts rt-helpers.ts task-0094-fanout.test.ts
ai-chat.integration.test.ts ai-database.integration.test.ts ai-generate.integration.test.ts ai-rag.integration.test.ts ai-writing.integration.test.ts api-keys.integration.test.ts audit-completeness.integration.test.ts audit-export-s3.integration.test.ts auth.integration.test.ts automation-pipeline.integration.test.ts automations.integration.test.ts blocks.integration.test.ts cache-invalidation.integration.test.ts comments.integration.test.ts databases.integration.test.ts files-lifecycle.integration.test.ts files-pipeline.integration.test.ts files-security.integration.test.ts files.integration.test.ts forms-responses.integration.test.ts forms.integration.test.ts oauth.integration.test.ts openapi.contract.test.ts org-admin.integration.test.ts package.json pages.integration.test.ts permissions.integration.test.ts README.md replica-routing.integration.test.ts retention-engine.integration.test.ts scim.integration.test.ts search.integration.test.ts sso.integration.test.ts tsconfig.json vitest.config.ts webhooks.integration.test.ts workspace.integration.test.ts
performance/28
fixtures/1search-100k.ts
helpers/2seed-100k.mjs seed-1k-load.mjs
reports/7api-load-smoke.json database-load-smoke.json editor-local.json realtime-load.json search-full.json search-last.json search-reduced.json
api-load.js api.js archive.tar database-load.js database.js editor-local.mjs extract-100k-env.mjs package.json README.md realtime-1k.js realtime-load.js realtime.js run-realtime-load.sh search-search.k6.js search-summary.json seed-100k.mjs threshold-breach-demo.js verify-zero-op-loss.mjs
security/16
helpers/1app.ts
audit-report.test.ts auth-paths.test.ts deps.test.ts formula-fuzz.test.ts gitleaks-config.test.ts headers.test.ts images.test.ts oracle.ts package.json permission-fuzz.test.ts rate-limits.test.ts README.md tsconfig.json upload-abuse.test.ts vitest.config.ts
README.md
.dockerignore .env .env.bak-task0125 .env.example .eslintrc.json .gitignore .npmrc .prettierignore .prettierrc.json AGENTS.md ARCHITECTURE.md CHANGELOG.md CONTRIBUTING.md gitleaks.toml LICENSE package.json pnpm-lock.yaml pnpm-workspace.yaml PRODUCT-SPEC.md README.md ROADMAP.md SECURITY.md tsconfig.json turbo.json
phase-13-api.mddocs/tasks/phase-13-api.md← tasks79,305 B← Back to the app

Phase 13 — Public API

Purpose: Task specs for Phase 13 — the public REST API v1: formalization of the API surface (auth, scopes, rate limits, idempotency, versioning, error codes), the OpenAPI contract + interactive docs, the API-keys management UI, OAuth2 (authorization code + PKCE), production webhooks (signing, retries, DLQ, event-catalog audit, incoming webhooks), and the in-app developer hub.

Phase exit criteria (ROADMAP.md, Phase 13):

  • OpenAPI contract matches live endpoints (CI check).
  • Webhook retry with backoff proven.
  • API-key auth E2E-tested.

Task range: TASK-0127 … TASK-0130 (4 tasks — this agent owns exactly TASK-0127..TASK-0130; TASK-0096..0120 are owned by other agents).

Task Table

ID Title Estimate
TASK-0127 Public REST API v1 formalization (auth, scopes, rate limits, idempotency, versioning, OpenAPI + docs) L
TASK-0128 API keys management UI + integration E2E M
TASK-0129 OAuth2 authorization code + PKCE M
TASK-0130 Webhooks production (signing, retries, DLQ, event catalog, incoming webhooks) + developer hub L

Spec conflicts & decisions recorded (per AGENTS rule 29)

  1. Per-key rate-limit default: the task brief says default 100/min for API keys, but docs/api/authentication.md §11 (published convention, Phase 1 artifact) says "Per API key: 600 req/min, or the key's rateLimit if set". This phase follows the published docs (600/min default) because docs are the external contract and AGENTS.md says to preserve backward compatibility; the brief's 100/min is treated as a product-tuning decision for a later change. The key's rateLimit field always wins when set.
  2. Webhook signing secret storage: the task brief says the raw signing secret is stored AES-GCM encrypted with MASTER_ENCRYPTION_KEY, while the current Prisma model Webhook.secretHash stores a hash. Both are needed and not contradictory: secretHash (SHA-256) is kept for verification of incoming webhooks only when the raw secret is unrecoverable — the production path stores the AES-GCM-encrypted raw secret (new encrypted field) so that signature verification can recompute HMACs, and secretHash is retained for the incoming-webhook replay/verification path. Decision: add Webhook.secretEncrypted Bytes (migration in TASK-0130); secretHash stays populated for all rows (legacy + incoming). Recorded here, not guessed.

Phase Completion Checklist


TASK-0127

Title

Public REST API v1 formalization: auth, scopes, rate limits, idempotency, versioning, OpenAPI + interactive docs

Objective

Make the existing /api/v1 endpoints the formal public surface: API-key authentication with scope enforcement, per-key rate limiting, POST idempotency, a versioning/deprecation policy, canonical error codes on every public route, and a machine-checked OpenAPI contract served interactively.

Background

Phase 2+ built /api/v1 endpoints (pages, databases, records, search, files, comments, workspaces — see docs/api/pages.md, docs/api/databases.md, docs/api/blocks.md, docs/api/workspaces.md) consumed by the web app with JWTs. docs/api/authentication.md already defines the API-key format (fk_ prefix, READ/WRITE/ADMIN scopes, X-Factory-Workspace header, per-key rate limit), the canonical error envelope + code table (§9.1), rate-limit headers (§11), and idempotency semantics. The Prisma models ApiKey (keyHash, prefix, scopes, rateLimit, lastUsedAt, expiresAt, revokedAt) and Integration (holds oauthApps config, TASK-0129) exist. This task does not add resources — it formalizes, secures, and contracts the surface.

Requirements

Acceptance Criteria

Backend Changes

Frontend Changes

Database Changes

API Changes

Tests

Security

Documentation

Dependencies

Definition of Done


TASK-0128

Title

API keys management UI + integration E2E

Objective

Ship the Developers section of workspace settings (create / list / revoke API keys) and prove the full key lifecycle E2E: key created → create page via curl → GET → PATCH, and READ-key POST rejection.

Background

TASK-0127 formalized API-key auth. The key-management endpoints (POST/GET/DELETE /workspaces/:workspaceId/api-keys per docs/api/authentication.md §7.1–7.3) exist (or are landed by TASK-0127's prerequisite). The workspace settings shell from Phase 2 has a "Developers" placeholder (the Integrations placeholder exists; Developers is added as a sibling tab). ApiKey fields: name, prefix, scopes (READ|WRITE|ADMIN), rateLimit?, lastUsedAt?, expiresAt?, revokedAt?, createdById. The raw key (fk_live_…) appears only in the create response.

Requirements

Acceptance Criteria

Backend Changes

Frontend Changes

Database Changes

API Changes

Tests

E2E result (TASK-0128)

developers.spec.ts (4 tests: desktop owner lifecycle + curl roundtrip + revoke + audit; desktop member tab-absence; mobile owner lifecycle; mobile member tab-absence) at the default workers: 2 config, repeated until stable under the FINAL code (fixes A+B+C+D server/client + D2 test-side, per C-13.5/C-13.6): run 1 = 3/4 (the double hard-goto re-render step — D2 above; run 1 ran under A/B/C only, before D/D2). Runs 2, 3, 4 = 4/4 each (31–45 s each). DB signal confirms the root fix, not a test band-aid: post-fix window shows 0 auth.refresh_reuse_detected (all 39 are the pre-fix baseline) and 2 auth.refresh_stale_retry (the new benign path firing on the cross-tab rotation race), and 0 live refresh tokens stranded on a revoked session (the pre-fix orphan defect class is gone). The pre-fix solo runs were already clean (5/5); the flake required the parallel fresh-context bootstraps that the single-flight + stale-grace + cookie-clear fixes now absorb. Diagnostic probe specs (zz-state.spec.ts / zz-owner2.spec.ts) were deleted before commit.

Security

Documentation

Dependencies

Definition of Done


TASK-0129

Title

OAuth2 authorization code + PKCE for third-party integrations

Objective

Implement the OAuth2 authorization-code flow with mandatory PKCE for third-party apps: registered-app config in integrations.config.oauthApps, the consent screen, single-use 10-minute codes, the token endpoint with refresh rotation, and the revoke endpoint — per the contract in docs/api/authentication.md §8.

Background

Docs §8 specifies the flow, endpoints, and error codes; Integration (workspace-scoped, config Json) is where oauthApps live: an org/workspace registers an app as {clientId, clientSecret? (hashed; absent = public client, PKCE mandatory), name, logoUrl?, redirectUris[], scopes[], grantTypes:["authorization_code","refresh_token"], createdAt}. JWTs issued here carry client_id + scope (no fixed workspaceId); each request then carries X-Factory-Workspace validated against the user's memberships and the scope grant (docs §8.2). Audit events: oauth.code_issued, oauth.token_issued, oauth.token_revoked. Refresh rotation follows §1.2 (opaque rotating refresh tokens, reuse detection).

Requirements

Acceptance Criteria

Backend Changes

Frontend Changes

Database Changes

API Changes

Tests

Security

Documentation

Dependencies

Definition of Done


TASK-0130

Title

Webhooks production: signing, retries, DLQ, event catalog, incoming webhooks + developer hub

Objective

Make webhooks production-grade: HMAC-SHA256-signed deliveries with an AES-GCM-encrypted signing secret, exponential-backoff retry (8 attempts) with DLQ + delivery log + resubmit, a proven-complete event catalog, signed incoming webhooks with replay protection, and the in-app developer hub (overview, keys, webhooks + delivery inspector, event explorer, curl examples).

Background

Webhook (url, secretHash, events[], active) and WebhookDelivery (status, attempts, statusCode, error, deliveredAt, nextRetryAt) exist; the worker webhooks queue + processor are scaffolded; packages/shared has the domain event names and the event bus. Docs: docs/api/webhooks.md (subscriptions CRUD contract), docs/api/authentication.md (error envelope, rate limits). MASTER_ENCRYPTION_KEY exists in .env.example (application-level secret encryption). Catalog events to be proven: page.created|updated|deleted|shared, database.created|updated, record.created|updated, comment.created, form.submitted, automation.executed, file.uploaded, api_key.created. (The brief also lists these as the audit-catalog; the webhooks catalog reuses the same event names.)

Requirements

Acceptance Criteria

Backend Changes

Frontend Changes

Database Changes

API Changes

Tests

Security

Documentation

Dependencies

Definition of Done


Recorded conflicts (AGENTS rule 29)

C-13.1 — TASK-0127 per-key rate-limit default. The phase brief text said "100 req/min"; docs/api/authentication.md §11 (the published contract, precedent over the brief) and phase decision #1 say 600 req/min. Resolution: 600, as a dedicated RATE_LIMIT_API_KEY env (default 600), per-key bucket rl:api:{apiKeyId}; keys with their own rateLimit always win. Recorded, not guessed (docs/api/authentication.md §11 governs).

C-13.2 — TASK-0128 create-form bounds. The task text says name ≤64 and rate limit 1–10 000; the landed server DTO (the TASK-0127 prerequisite, api-keys.controller.ts) enforces name ≤100 and rate limit 1–100 000; the published docs/api/authentication.md §7 is silent on both. Resolution: the UI follows the SERVER (authoritative): maxLength=100, rate-limit input 1–10 000 (the task's practical window — a strict subset the server also accepts; the "600 (default)" placeholder stays). The UI never rejects what the server accepts.

C-13.3 — TASK-0128 "asserted via the audit API". No audit READ endpoint existed when this task was written. Resolution: added the minimal GET /api/v1/workspaces/:id/audit (OWNER/ADMIN, newest-first, bounded, optional action filter) — Phase 14's audit viewer builds on it.

C-13.4 — TASK-0128 mobile E2E project: isMobile vs the layout viewport. The DoD's "Mobile behavior" row required the Developers tab to be usable at < 640 px, and the pre-existing chromium-mobile Playwright project spread devices["iPhone 13"] (isMobile: true, iPhone UA, hasTouch) pinned to chromium. With isMobile, Chromium splits the layout viewport from a 375px visual viewport and processes the page's width=device-width meta differently; Playwright 1.49's CDP actionability hit-test then desynced on those pages — a dialog/table button's center intermittently resolved onto the backdrop or another node while the page's own elementFromPoint at the same coordinate returned the button (the reported interceptor varied run-to-run: backdrop / footer / fieldset / input), hanging every locator.click() and even locator.focus() (its pre-check runs the same hit-test). The app itself is correct: the viewport meta is served at byte 92 of the HTML, and with the create dialog open no element exceeds 375px and scrollWidth stays 375 (probed) — the app's viewport export (apps/web/src/app/layout.tsx, width=device-width, initial-scale=1) made the layout actually 375px on mobile. Resolution: the chromium-mobile project now uses a plain chromium context with viewport: 375×812, deviceScaleFactor: 3 and NO isMobile — identical CSS layout (breakpoints key off CSS px, identical at 375 either way), stable hit-test, verified 4/4 stable over repeated full runs. Trade-off (recorded, not guessed): the iPhone user agent and hasTouch are no longer emulated; the app does no UA sniffing and no touch-only interactions, so nothing under test changes. The test-side safeClick() helper in developers.spec.ts (plain click → coordinate-free el.click() fallback, with the caller still asserting the full post-click state) remains as defense-in-depth against any future emulation regression.

C-13.5 — TASK-0128 E2E: the ready-wait reload loop livelocked the auth bootstrap (CORRECTED diagnosis — initially recorded as a worker-count issue). The Developers spec flaked at its first-paint ready check and later at getByRole("row", { name: /CI/ }) — on BOTH desktop and mobile. The first hypothesis (recorded here for the record) blamed worker count vs the unbuilt dev stack: the instrumented poll showed the create→invalidate→refetch cycle completes in ~6.5s when idle, and worker experiments (CLI --workers=2 3/3 green, config workers: 2 2/3 failed, --workers=1 3/3 green) were inconsistent, so worker load was never confirmed as the cause. The decisive experiments: (a) a state-dump run captured the stuck page at the (app) layout's "Loading workspace…" auth gate (mainLen=0, no localStorage) with the network log showing POST /auth/refresh 200 + GET /auth/me 200 already completed; (b) a manual probe FROM the page's own cookie jar (plain fetch, bypassing the app) returned refresh:200, hasToken:true, /auth/me 200 user:demo@factory.local — the server session was provably valid, so the app's React state simply never committed the user; (c) a single uninterrupted load (no reloads) with a 30s budget cleared in 2.1–2.9s, 3/3. Root cause: the openDevelopers() helper's "ready or reload" loop reloaded every ~2–3s, but the fresh-context auth bootstrap (cookie → POST /auth/refresh → GET /auth/me → authStore.setUser) needs ~3s after the page's JS hydrates — each reload aborted the in-flight refresh→me chain before React processed the 200 response, so no load ever reached the setUser commit (the 200s were seen at the network layer; the component was already gone). The app is correct (single loads clear 3/3); the helper was the defect. Resolution: openDevelopers() now does one goto + toBeVisible({ timeout: 20_000 }) with NO reloads (20s absorbs a cold dev-server compile; a genuine stuck gate still fails). workers: 2 in all environments and the 20s budget on the CI-row assertion are RETAINED: 2 workers is a reasonable cap for the shared dev stack (CI parity) and the row budget covers the cold-refetch case that the poll proved can exceed 10s under concurrent compile — but neither was the root cause of the flake. Verified post-fix: see TASK-0128 E2E result line.

C-13.6 — TASK-0128 E2E flake #2: the parallel double-rotation race killed the session family (PRODUCT FIX, not a test-side band-aid). Symptom: under the default parallel config (workers: 2, 8 contexts each fresh-logging-in the demo user) the Developers spec flaked at a rate of ~1/3 owner-test runs; the stuck page parked at /w/default behind the (app) auth gate ("Loading workspace…", mainLen=0) with a redirect loop between /login and /w/default. Solo (single-context) runs were 5/5 clean, so the flake required concurrency — the probe that cracked it was a single-context double load (FAM probe): both loads cleared, but the demo user's DB then held 32 live refresh tokens, including rows with revokedAt=f, replacedBy=f (orphaned live tokens) sitting beside the chained revokedAt=t → replacedBy=t rows. The full root chain, confirmed at every level:

  1. Client (2 refreshes per page load): reactStrictMode: true (apps/web/next.config line 3) double-mounts the (app) layout, so the useAuth bootstrap effect ran twice per load, each instance with a fresh hydrated ref → 2 concurrent POST /auth/refresh (COUNT probe 5/5 solo: load-refreshes=2 me=1). The bootstrap called authApi.refresh() → mutatingApiFetch("/auth/refresh") — which bypassed the module-level single-flight refreshAccessToken()/refreshInFlight (api.ts) that only the 401-retry path used. The comment at that call site ("reuses the same primitive") was false — the divergence was invisible.
  2. Server (non-atomic rotation → orphaned live tokens): auth.service.ts refresh() did refreshToken.create(new) then refreshToken.update(old → {revokedAt, replacedBy}) as two separate awaits. Two concurrent refreshes of the same row both passed the row.revokedAt check, both created new tokens, and the unconditional update was last-writer-wins on replacedBy — leaving the loser's new row live and unreachable (the orphaned rows above). Every E2E context leaked a token per load; 8 contexts × fresh logins × loads = 32 live rows.
  3. Server (stale-vs-reuse conflation → family kill): a presentation of any revoked row — including the benign "my concurrent twin already rotated" case — was treated as a reuse attack: the whole user token set + all ACTIVE sessions revoked, audit auth.refresh_reuse_detected, 401 refresh_token_reused. Worse, the kill path did not clear the httpOnly cookie, and the middleware (apps/web/src/middleware.ts line 28) gates on cookie existence only — so a dead-but-present cookie bounced /login → /w/default, the (app) gate bootstrapped with the revoked cookie → 401 → re-login attempt → …: the exact redirect loop + parked gate observed in the flake.

Rule-29 conflicts recorded (code vs architecture doc — the code was fixed to match the doc):

Security trade-off (recorded, not guessed): the stale-retry grace means a stolen token can be replayed a bounded number of times (each replay 401s without collateral) as long as the chain advances legitimately — i.e. the victim's own client keeps rotating. Detection still fires on the first presentation where the chain has moved on WITHOUT the attacker (dead successor), at which point the whole family dies. This is precisely the doc's threat model (§T2 "rotation with reuse detection + family kill") and strictly reduces false-positive session loss (a family kill of a multi-device user who merely had two tabs race is worse than the attack it prevented, since the victim re-logs in).

Fix (4 parts, all in this task's diff):

Tests: tests/integration/auth.integration.test.ts — the old "refresh reuse" test (one rotation + replay ⇒ family killed) is rewritten into the doc's two cases: stale retry (successor live ⇒ 401 refresh_token_stale, successor still 200, audit stale-not-reuse) and reuse attack (two rotations then replay the first ⇒ 401 refresh_token_reused, latest token dead, all tokens + session REVOKED, reuse audit fires); plus a concurrency test firing two in-flight rotations of one token ⇒ exactly [200, 401-stale], exactly ONE live token in the contested session (no orphaned live row), chain intact (first.replacedBy = winner). Web unit tests (apps/web/src/lib/__tests__/auth-refresh.test.ts): single-flight dedup — 2 concurrent callers → 1 fetch, shared outcome, in-flight slot resets after settle, stale/reused errors propagate typed (isStaleRefreshError table); (auth-store.test.ts): clear() ends initialization, setUser lifecycle. Reported, not fixed (environment-bound): the "rate limit: sustained login failures → 429" integration test fails in this environment: the shared test app raises RATE_LIMIT_AUTH (helper ?? 100000, repo .env 10000), so 20 logins in the 60s sliding window can never trip a 429 — the test as written only passes with an unset limit (zod default 10). The helper's own comment says throttling is unit-tested separately, but no such unit test exists (apps/api/src/common/__tests__/ has none) — the behavior is currently unverified anywhere. NOT a regression from this fix (the diff touches no login/rate-limit path); needs a dedicated fix in its own task.

E2E stability re-verification: developers.spec.ts at the default workers: 2 config, repeated until stable: run 1 (fixes A/B/C loaded, API tsx watch reloaded) = 3/4 — the 4th test failed at the double hard-goto re-render step (D2 above). Run 1 proved the PRIMARY flake (fresh-context bootstrap double-rotation → family kill → stuck gate) is GONE (that test now passes; the failure moved to the unrelated stress step). After fix D + D2, runs 2–3+ must be 4/4 (see the TASK-0128 E2E result line). The diagnostic probe specs zz-state.spec.ts / zz-owner2.spec.ts were deleted before commit. C-13.7 — TASK-0129 rule-29 conflicts recorded (task spec vs doc / design decisions — the TASK text wins where it itself mandates behavior; doc-only details follow the doc):

TASK-0129 implementation notes (verified):

C-13.8 — TASK-0130 rule-29 conflicts recorded (published doc vs task text vs implementation):