This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
<!-- SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0 -->
|
||||
# The mongodb profile
|
||||
|
||||
**Status (source review 2026-10-21): adapter and migration assets, not a selectable
|
||||
app profile.** `kit template:prune --profile mongodb` is still refused; its error
|
||||
incorrectly says no adapter exists, although `@conusai-kit/data-mongo` is
|
||||
implemented. The web/worker composition is unfinished. The tables and generated-
|
||||
app steps below describe the target design; repository/transaction and migration
|
||||
tests do not establish a generated application deployment.
|
||||
|
||||
|
||||
The persistence profile for an app whose primary store is MongoDB instead of Postgres
|
||||
(spec §5.1): the same procedures, the same modules, the same migrations discipline, on the
|
||||
official `mongodb` driver (`@conusai-kit/data-mongo`) with jobs on BullMQ over Valkey
|
||||
(`@conusai-kit/jobs-bullmq`).
|
||||
|
||||
| | postgres (default) | mongodb (this profile) |
|
||||
|---|---|---|
|
||||
| Primary store | Postgres 18 | MongoDB 8.0, **single-node replica set** (below) |
|
||||
| Data adapter | `@conusai-kit/data-kysely` | `@conusai-kit/data-mongo` |
|
||||
| Jobs | pg-boss (Postgres) | BullMQ on Valkey (`@conusai-kit/jobs-bullmq`) |
|
||||
| Tenant wall | repository predicate + RLS (three roles, AT-D20) | repository predicate + compound indexes leading with `org_id` — MongoDB has no RLS |
|
||||
| Links | `postgres`, `identity` | `mongodb`, `redis`, `identity` |
|
||||
| Process env | `POSTGRES_URL`, `POSTGRES_READER_URL`, `POSTGRES_MIGRATE_URL` | `MONGODB_URL`, `REDIS_URL` |
|
||||
|
||||
## The replica_set requirement (AT-D15)
|
||||
|
||||
**Create the MongoDB service with `replica_set` set.** A managed MongoDB is a standalone server
|
||||
unless `replica_set` is given at creation (the console's create form offers it and states it
|
||||
cannot be changed afterwards), and a standalone server has no multi-document transactions — a
|
||||
`unitOfWork.run` on it would be silently non-atomic. `@conusai-kit/data-mongo` therefore asks the
|
||||
server what it is at boot (`hello`'s `setName`) and refuses to start against a standalone mongod
|
||||
with a `MongoTopologyError` that names this setting. A single-node replica set is enough: with
|
||||
`replica_set` set, the platform starts mongod with `--replSet` and `rs.initiate()`, and the
|
||||
injected `MONGODB_URL` carries `directConnection=true`. The `conusai.json` in this folder links
|
||||
`mongodb` — that link is only valid for an app whose MongoDB service was created this way.
|
||||
|
||||
## What this folder carries
|
||||
|
||||
- `conusai.json` — the profile's deployment contract: the same three services, links `mongodb` +
|
||||
`redis` + `identity`. There is no `mongodb.migrate` flag: the three-role split the postgres
|
||||
profile declares (data-services DS21) exists to make row-level security bind, and MongoDB has
|
||||
none, so every process holds the one `MONGODB_URL` and ordering is compose's
|
||||
`service_completed_successfully` alone (AT-D14).
|
||||
- `compose.yaml`, `compose.dev.yaml` — the profile's compose files. The dev overlay runs
|
||||
`mongo:8.0` as a single-node replica set (`--replSet` plus a one-shot `mongo-init` that runs
|
||||
`rs.initiate()`) and `valkey/valkey:9-alpine`, the images the platform's catalog offers.
|
||||
- `migrations/` — the kernel collections (tenancy, sign-in, files, proposals, outbox, idempotency
|
||||
keys) as declarative MongoDB commands in JSON — a collection with its `$jsonSchema` validator
|
||||
generated from the entity's zod schema, and every unique group and index as a compound index
|
||||
leading with `org_id` — generated by `mongoSchemaCommands` from the same entity definitions as
|
||||
the postgres files and committed, forward-only. A module's own MongoDB migrations live with the
|
||||
module: `modules/<id>/adapters/mongo/migrations/`, declared in its manifest as
|
||||
`migrations: { postgres: "migrations", mariadb: "...", mongodb: "adapters/mongo/migrations" }`.
|
||||
|
||||
## Target generated-app changes (not wired)
|
||||
|
||||
The profile is chosen at generation time (`.conusai/template.json` `profile`), and
|
||||
`kit template:prune --profile mongodb` removes the other dialects. Concretely:
|
||||
|
||||
1. `config/src/env.ts` reads `MONGODB_URL` (every process) instead of the three Postgres URLs —
|
||||
one login, because there is no RLS to bind (AT-D20 is Postgres-only).
|
||||
2. `apps/web` and `apps/worker` compose `connectMongoDataSourceFromEnv` (which refuses a
|
||||
standalone server, above) and the worker's queue is `createBullmqJobQueue`/`createBullmqWorker`
|
||||
over `REDIS_URL`.
|
||||
3. The migrate job runs `runMongoMigrationsFromEnv` over `profiles/mongodb/migrations/` (moved to
|
||||
`migrations/mongodb/`) and the modules' `adapters/mongo/migrations/`, each JSON file a
|
||||
`mongoCommandsMigration`.
|
||||
4. This folder's `conusai.json`, `compose.yaml` and `compose.dev.yaml` replace the root ones.
|
||||
|
||||
The dialect differences are explicit, never generated at run time (spec §5.3): a module's MongoDB
|
||||
schema is its own numbered folder, reviewed like any migration.
|
||||
|
||||
## Proof
|
||||
|
||||
- `@conusai-kit/data-mongo` passes the shared repository and capability contract suites in
|
||||
testcontainers against MongoDB 8 running as a single-node replica set, including a multi-entity
|
||||
UnitOfWork commit and rollback — the tenant predicate is the wall, and the contract is what
|
||||
proves it. Against a standalone mongod the adapter refuses to boot with `MongoTopologyError`,
|
||||
naming `replica_set` (AT-D15). The suite's image is `mongo:8.2`, not `mongo:8.0`: the 8.0 binary
|
||||
refuses to start on Linux kernels 6.19 and newer (SERVER-121912, the TCMalloc/rseq
|
||||
incompatibility — the refusal is compiled into the server), which covers current development
|
||||
hosts; the topology under test is the same on either minor, and the platform's managed image is
|
||||
`mongodb-walg:8.0`. The same applies to this folder's `compose.dev.yaml` on such a kernel: bump
|
||||
its `mongo:` tag to 8.2.
|
||||
- `@conusai-kit/jobs-bullmq` passes the shared JobQueue contract against `valkey/valkey:9` in
|
||||
testcontainers.
|
||||
- `scripts/vendor/test-template.sh app --profile mongodb` runs the template's gate and then
|
||||
applies this folder's and the modules' MongoDB migrations to a real MongoDB 8 container
|
||||
started as a single-node replica set, and probes that the adapter boots on it and refuses a
|
||||
standalone server — so the committed schema is proven against the engine, not just generated.
|
||||
@@ -0,0 +1,144 @@
|
||||
# SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
|
||||
# Local development for the mongodb profile: MongoDB and Valkey in Docker, the fake platform, the
|
||||
# migrate job, the demo data, the worker and the web shell. Nothing here is deployed: the platform
|
||||
# reads compose.yaml alone (conusai.json's `compose.file`).
|
||||
#
|
||||
# The dev MongoDB runs as a single-node replica set (AT-D15): `--replSet` plus the one-shot
|
||||
# `mongo-init` container's rs.initiate(), because a standalone mongod has no multi-document
|
||||
# transactions and the adapter refuses to boot against one. The advertised member host is the
|
||||
# compose service name, so app containers reach it as `mongo:27017` with `directConnection=true`;
|
||||
# `pnpm dev` on this machine uses the loopback publication with `directConnection=true` as well.
|
||||
x-development: &development
|
||||
NODE_ENV: development
|
||||
CONUSAI_FAKE_PLATFORM: "1"
|
||||
CONUSAI_API_URL: http://platform:4010/api
|
||||
CONUSAI_API_TOKEN: dev-token
|
||||
CONUSAI_PROJECT_ID: "1"
|
||||
CONUSAI_ORG_ID: dev
|
||||
|
||||
services:
|
||||
mongo:
|
||||
image: mongo:8.0
|
||||
command: ["mongod", "--replSet", "rs0", "--bind_ip_all"]
|
||||
volumes:
|
||||
- mongo-data:/data/db
|
||||
# Published on loopback only, for `pnpm dev`, which runs the processes on this machine.
|
||||
ports: ["127.0.0.1:${DEV_MONGO_PORT:-57017}:27017"]
|
||||
healthcheck:
|
||||
test: ["CMD", "mongosh", "--quiet", "--eval", "db.adminCommand({ ping: 1 })"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 20
|
||||
restart: unless-stopped
|
||||
|
||||
mongo-init:
|
||||
image: mongo:8.0
|
||||
command:
|
||||
- mongosh
|
||||
- --host
|
||||
- mongo:27017
|
||||
- --quiet
|
||||
- --eval
|
||||
- |
|
||||
try {
|
||||
rs.initiate({ _id: "rs0", members: [{ _id: 0, host: "mongo:27017" }] })
|
||||
} catch (e) {
|
||||
if (!/already initialized/.test(String(e))) throw e
|
||||
}
|
||||
depends_on:
|
||||
mongo:
|
||||
condition: service_healthy
|
||||
restart: "no"
|
||||
init: true
|
||||
|
||||
valkey:
|
||||
image: valkey/valkey:9-alpine
|
||||
volumes:
|
||||
- valkey-data:/data
|
||||
ports: ["127.0.0.1:${DEV_VALKEY_PORT:-56380}:6379"]
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "valkey-cli ping | grep -q PONG"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 20
|
||||
restart: unless-stopped
|
||||
|
||||
platform:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
target: runtime
|
||||
working_dir: /app
|
||||
command: ["node", "node_modules/@conusai-kit/testing/dist/fake-platform/cli.js"]
|
||||
environment:
|
||||
PORT: "4010"
|
||||
HOST: 0.0.0.0
|
||||
PUBLIC_URL: http://platform:4010
|
||||
expose: ["4010"]
|
||||
healthcheck:
|
||||
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:4010/__e2e/health').then(r=>process.exit(r.ok?0:1),()=>process.exit(1))"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 20
|
||||
init: true
|
||||
restart: unless-stopped
|
||||
|
||||
migrate:
|
||||
environment: *development
|
||||
depends_on:
|
||||
mongo-init:
|
||||
condition: service_completed_successfully
|
||||
|
||||
seed:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
target: runtime
|
||||
working_dir: /app
|
||||
command: ["node", "apps/worker/dist/seed-main.js"]
|
||||
environment:
|
||||
<<: *development
|
||||
CONUSAI_PUBLIC_URL: ${CONUSAI_PUBLIC_URL:-http://127.0.0.1:3000}
|
||||
MONGODB_URL: ${MONGODB_URL}
|
||||
REDIS_URL: ${REDIS_URL}
|
||||
depends_on:
|
||||
migrate:
|
||||
condition: service_completed_successfully
|
||||
platform:
|
||||
condition: service_healthy
|
||||
restart: "no"
|
||||
init: true
|
||||
|
||||
web:
|
||||
environment:
|
||||
<<: *development
|
||||
AUTH_DEV_LOGIN: "1"
|
||||
AUTH_INSECURE_COOKIES: "1"
|
||||
ports: ["127.0.0.1:3000:3000"]
|
||||
depends_on:
|
||||
mongo-init:
|
||||
condition: service_completed_successfully
|
||||
valkey:
|
||||
condition: service_healthy
|
||||
migrate:
|
||||
condition: service_completed_successfully
|
||||
seed:
|
||||
condition: service_completed_successfully
|
||||
platform:
|
||||
condition: service_healthy
|
||||
|
||||
worker:
|
||||
environment: *development
|
||||
depends_on:
|
||||
mongo-init:
|
||||
condition: service_completed_successfully
|
||||
valkey:
|
||||
condition: service_healthy
|
||||
migrate:
|
||||
condition: service_completed_successfully
|
||||
platform:
|
||||
condition: service_healthy
|
||||
|
||||
volumes:
|
||||
mongo-data:
|
||||
valkey-data:
|
||||
@@ -0,0 +1,147 @@
|
||||
# SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
|
||||
# The mongodb profile's compose.yaml: the same three processes from one image as the default
|
||||
# (postgres) profile, with this profile's two links in place of the three Postgres roles
|
||||
# (spec §5.1).
|
||||
#
|
||||
# MongoDB has no row-level security, so there is no owner/runtime/reader split to enforce it
|
||||
# with: every process holds the one MONGODB_URL the platform injects for a linked MongoDB, and
|
||||
# the tenant wall is the repository predicate, proven by the kit's contract suite
|
||||
# (@conusai-kit/data-mongo runs it against MongoDB 8 as a single-node replica set). Jobs are
|
||||
# BullMQ on the linked Valkey (REDIS_URL).
|
||||
#
|
||||
# The linked MongoDB service must be created with `replica_set` set (AT-D15): a standalone server
|
||||
# has no multi-document transactions, and the adapter refuses to boot against one. When
|
||||
# `replica_set` is set the platform starts mongod with --replSet and rs.initiate(), and the
|
||||
# injected MONGODB_URL carries directConnection=true.
|
||||
#
|
||||
# Ordering is the default profile's mechanism unchanged (decision AT-D14): migrate carries
|
||||
# `restart: "no"`, and web and worker wait for it with `condition: service_completed_successfully`.
|
||||
services:
|
||||
web:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
target: runtime
|
||||
working_dir: /app/apps/web
|
||||
command: ["node", "node_modules/next/dist/bin/next", "start"]
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
PORT: "3000"
|
||||
CONUSAI_API_URL: ${CONUSAI_API_URL}
|
||||
CONUSAI_API_TOKEN: ${CONUSAI_API_TOKEN}
|
||||
CONUSAI_PROJECT_ID: ${CONUSAI_PROJECT_ID}
|
||||
CONUSAI_PUBLIC_URL: ${CONUSAI_PUBLIC_URL}
|
||||
CONUSAI_ORG_ID: ${CONUSAI_ORG_ID}
|
||||
CONUSAI_ORG_SLUG: ${CONUSAI_ORG_SLUG:-}
|
||||
CONUSAI_RELEASE: ${CONUSAI_RELEASE}
|
||||
CONUSAI_ENVIRONMENT: ${CONUSAI_ENVIRONMENT:-}
|
||||
CONUSAI_DSN: ${CONUSAI_DSN:-}
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT: ${OTEL_EXPORTER_OTLP_ENDPOINT:-}
|
||||
OTEL_EXPORTER_OTLP_PROTOCOL: ${OTEL_EXPORTER_OTLP_PROTOCOL:-}
|
||||
OTEL_EXPORTER_OTLP_HEADERS: ${OTEL_EXPORTER_OTLP_HEADERS:-}
|
||||
OTEL_SERVICE_NAME: ${OTEL_SERVICE_NAME:-}
|
||||
OTEL_SERVICE_VERSION: ${OTEL_SERVICE_VERSION:-}
|
||||
AI_MODEL: ${AI_MODEL:-}
|
||||
LOG_LEVEL: ${LOG_LEVEL:-}
|
||||
MONGODB_URL: ${MONGODB_URL}
|
||||
REDIS_URL: ${REDIS_URL}
|
||||
AUTH_SESSION_SECRET: ${AUTH_SESSION_SECRET}
|
||||
OIDC_ISSUER: ${OIDC_ISSUER:-}
|
||||
OIDC_WEB_CLIENT_ID: ${OIDC_WEB_CLIENT_ID:-}
|
||||
OIDC_WEB_CLIENT_SECRET: ${OIDC_WEB_CLIENT_SECRET:-}
|
||||
OIDC_RESOURCE: ${OIDC_RESOURCE:-}
|
||||
OIDC_INTROSPECTION_CLIENT_ID: ${OIDC_INTROSPECTION_CLIENT_ID:-}
|
||||
OIDC_INTROSPECTION_CLIENT_SECRET: ${OIDC_INTROSPECTION_CLIENT_SECRET:-}
|
||||
OIDC_RESOURCE_STATUS_URL: ${OIDC_RESOURCE_STATUS_URL:-}
|
||||
OIDC_SCOPES: ${OIDC_SCOPES:-}
|
||||
AUTH_PROVIDER_GENERATION: ${AUTH_PROVIDER_GENERATION:-}
|
||||
AUTH_COOKIE_NAME: ${AUTH_COOKIE_NAME:-}
|
||||
AUTH_SESSION_IDLE_SECONDS: ${AUTH_SESSION_IDLE_SECONDS:-}
|
||||
AUTH_SESSION_ABSOLUTE_SECONDS: ${AUTH_SESSION_ABSOLUTE_SECONDS:-}
|
||||
OIDC_AUDIENCE: ${OIDC_AUDIENCE:-}
|
||||
expose: ["3000"]
|
||||
depends_on:
|
||||
migrate:
|
||||
condition: service_completed_successfully
|
||||
healthcheck:
|
||||
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:3000/api/ready').then(r=>process.exit(r.ok?0:1),()=>process.exit(1))"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 20s
|
||||
init: true
|
||||
stop_grace_period: 20s
|
||||
restart: unless-stopped
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: "1.0"
|
||||
memory: 768M
|
||||
|
||||
worker:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
target: runtime
|
||||
working_dir: /app
|
||||
command: ["node", "apps/worker/dist/main.js"]
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
CONUSAI_API_URL: ${CONUSAI_API_URL}
|
||||
CONUSAI_API_TOKEN: ${CONUSAI_API_TOKEN}
|
||||
CONUSAI_PROJECT_ID: ${CONUSAI_PROJECT_ID}
|
||||
CONUSAI_ORG_ID: ${CONUSAI_ORG_ID}
|
||||
CONUSAI_ORG_SLUG: ${CONUSAI_ORG_SLUG:-}
|
||||
CONUSAI_RELEASE: ${CONUSAI_RELEASE}
|
||||
CONUSAI_ENVIRONMENT: ${CONUSAI_ENVIRONMENT:-}
|
||||
CONUSAI_DSN: ${CONUSAI_DSN:-}
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT: ${OTEL_EXPORTER_OTLP_ENDPOINT:-}
|
||||
OTEL_EXPORTER_OTLP_PROTOCOL: ${OTEL_EXPORTER_OTLP_PROTOCOL:-}
|
||||
OTEL_EXPORTER_OTLP_HEADERS: ${OTEL_EXPORTER_OTLP_HEADERS:-}
|
||||
OTEL_SERVICE_NAME: ${OTEL_SERVICE_NAME:-}
|
||||
OTEL_SERVICE_VERSION: ${OTEL_SERVICE_VERSION:-}
|
||||
AI_MODEL: ${AI_MODEL:-}
|
||||
LOG_LEVEL: ${LOG_LEVEL:-}
|
||||
MONGODB_URL: ${MONGODB_URL}
|
||||
REDIS_URL: ${REDIS_URL}
|
||||
WORKER_HEARTBEAT_FILE: /tmp/worker-heartbeat
|
||||
depends_on:
|
||||
migrate:
|
||||
condition: service_completed_successfully
|
||||
healthcheck:
|
||||
test: ["CMD", "node", "apps/worker/dist/healthcheck.js"]
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 20s
|
||||
init: true
|
||||
stop_grace_period: 30s
|
||||
restart: unless-stopped
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: "1.0"
|
||||
memory: 512M
|
||||
|
||||
migrate:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
target: runtime
|
||||
working_dir: /app
|
||||
command: ["node", "apps/worker/dist/migrate.js"]
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
CONUSAI_API_URL: ${CONUSAI_API_URL}
|
||||
CONUSAI_API_TOKEN: ${CONUSAI_API_TOKEN}
|
||||
CONUSAI_PROJECT_ID: ${CONUSAI_PROJECT_ID}
|
||||
# One login, not three: there is no RLS to bind, so the owner/runtime/reader split of the
|
||||
# postgres profile has no counterpart here (decision AT-D20 is Postgres-only, DS21).
|
||||
MONGODB_URL: ${MONGODB_URL}
|
||||
restart: "no"
|
||||
init: true
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: "1.0"
|
||||
memory: 512M
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"$schema": "https://build.conusai.com/schemas/conusai.schema.json",
|
||||
"schema_version": 2,
|
||||
"compose": {
|
||||
"file": "compose.yaml"
|
||||
},
|
||||
"services": {
|
||||
"web": {
|
||||
"public": {
|
||||
"port": 3000,
|
||||
"primary": true
|
||||
},
|
||||
"health_check": {
|
||||
"path": "/api/ready",
|
||||
"interval_seconds": 10,
|
||||
"timeout_seconds": 5
|
||||
},
|
||||
"size": "small"
|
||||
},
|
||||
"worker": {
|
||||
"size": "small"
|
||||
},
|
||||
"migrate": {}
|
||||
},
|
||||
"links": [
|
||||
{
|
||||
"type": "mongodb"
|
||||
},
|
||||
{
|
||||
"type": "redis"
|
||||
},
|
||||
{
|
||||
"type": "identity"
|
||||
}
|
||||
],
|
||||
"previews": {
|
||||
"enabled": true,
|
||||
"size": "small"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,933 @@
|
||||
[
|
||||
{
|
||||
"createCollection": "outbox",
|
||||
"validator": {
|
||||
"$jsonSchema": {
|
||||
"bsonType": "object",
|
||||
"required": [
|
||||
"_id",
|
||||
"org_id",
|
||||
"name",
|
||||
"payload",
|
||||
"created_at",
|
||||
"attempts",
|
||||
"published_at",
|
||||
"last_error",
|
||||
"deferrals",
|
||||
"deferred_since",
|
||||
"deferred_until"
|
||||
],
|
||||
"properties": {
|
||||
"_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"org_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"name": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"payload": {},
|
||||
"created_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"attempts": {
|
||||
"bsonType": "number"
|
||||
},
|
||||
"published_at": {
|
||||
"bsonType": ["string", "null"],
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"last_error": {
|
||||
"bsonType": ["string", "null"]
|
||||
},
|
||||
"deferrals": {
|
||||
"bsonType": "number"
|
||||
},
|
||||
"deferred_since": {
|
||||
"bsonType": ["string", "null"],
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"deferred_until": {
|
||||
"bsonType": ["string", "null"],
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "outbox",
|
||||
"keys": {
|
||||
"created_at": 1
|
||||
},
|
||||
"name": "outbox_pending_idx",
|
||||
"unique": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"createCollection": "idempotency_keys",
|
||||
"validator": {
|
||||
"$jsonSchema": {
|
||||
"bsonType": "object",
|
||||
"required": [
|
||||
"org_id",
|
||||
"workspace_id",
|
||||
"project_id",
|
||||
"procedure",
|
||||
"key",
|
||||
"response",
|
||||
"completed_at",
|
||||
"created_at"
|
||||
],
|
||||
"properties": {
|
||||
"_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"org_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"workspace_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"project_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"procedure": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"key": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"response": {},
|
||||
"completed_at": {
|
||||
"bsonType": ["string", "null"],
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"created_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "idempotency_keys",
|
||||
"keys": {
|
||||
"org_id": 1,
|
||||
"workspace_id": 1,
|
||||
"project_id": 1,
|
||||
"procedure": 1,
|
||||
"key": 1
|
||||
},
|
||||
"name": "idempotency_keys_scope_key",
|
||||
"unique": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"createCollection": "auth_api_keys",
|
||||
"validator": {
|
||||
"$jsonSchema": {
|
||||
"bsonType": "object",
|
||||
"required": ["_id", "version", "created_at", "updated_at", "org_id", "name", "token_hash", "prefix", "user_id"],
|
||||
"properties": {
|
||||
"_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"version": {
|
||||
"bsonType": "number"
|
||||
},
|
||||
"created_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"updated_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"org_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"name": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"token_hash": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"prefix": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"user_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"expires_at": {
|
||||
"bsonType": ["string", "null"]
|
||||
},
|
||||
"revoked_at": {
|
||||
"bsonType": ["string", "null"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "auth_api_keys",
|
||||
"keys": {
|
||||
"org_id": 1,
|
||||
"token_hash": 1
|
||||
},
|
||||
"name": "auth_api_keys_org_id_token_hash_key",
|
||||
"unique": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "auth_api_keys",
|
||||
"keys": {
|
||||
"org_id": 1,
|
||||
"user_id": 1
|
||||
},
|
||||
"name": "auth_api_keys_org_id_user_id_idx",
|
||||
"unique": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "auth_api_keys",
|
||||
"keys": {
|
||||
"org_id": 1,
|
||||
"prefix": 1
|
||||
},
|
||||
"name": "auth_api_keys_org_id_prefix_idx",
|
||||
"unique": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"createCollection": "auth_sessions",
|
||||
"validator": {
|
||||
"$jsonSchema": {
|
||||
"bsonType": "object",
|
||||
"required": [
|
||||
"_id",
|
||||
"version",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"user_id",
|
||||
"issuer",
|
||||
"subject",
|
||||
"handle_hash",
|
||||
"tokens",
|
||||
"access_token_expires_at",
|
||||
"last_seen_at",
|
||||
"absolute_expires_at"
|
||||
],
|
||||
"properties": {
|
||||
"_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"version": {
|
||||
"bsonType": "number"
|
||||
},
|
||||
"created_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"updated_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"user_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"issuer": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"subject": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"handle_hash": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"tokens": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"access_token_expires_at": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"last_seen_at": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"absolute_expires_at": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"revoked_at": {
|
||||
"bsonType": ["string", "null"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "auth_sessions",
|
||||
"keys": {
|
||||
"handle_hash": 1
|
||||
},
|
||||
"name": "auth_sessions_handle_hash_key",
|
||||
"unique": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "auth_sessions",
|
||||
"keys": {
|
||||
"user_id": 1
|
||||
},
|
||||
"name": "auth_sessions_user_id_idx",
|
||||
"unique": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "auth_sessions",
|
||||
"keys": {
|
||||
"absolute_expires_at": 1
|
||||
},
|
||||
"name": "auth_sessions_absolute_expires_at_idx",
|
||||
"unique": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"createCollection": "extensions",
|
||||
"validator": {
|
||||
"$jsonSchema": {
|
||||
"bsonType": "object",
|
||||
"required": [
|
||||
"_id",
|
||||
"version",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"org_id",
|
||||
"subject_type",
|
||||
"subject_id",
|
||||
"namespace",
|
||||
"payload",
|
||||
"payload_version"
|
||||
],
|
||||
"properties": {
|
||||
"_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"version": {
|
||||
"bsonType": "number"
|
||||
},
|
||||
"created_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"updated_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"org_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"subject_type": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"subject_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"namespace": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"payload": {
|
||||
"bsonType": "object"
|
||||
},
|
||||
"payload_version": {
|
||||
"bsonType": "number"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "extensions",
|
||||
"keys": {
|
||||
"org_id": 1,
|
||||
"subject_type": 1,
|
||||
"subject_id": 1,
|
||||
"namespace": 1
|
||||
},
|
||||
"name": "extensions_org_id_subject_type_subject_id_namespace_key",
|
||||
"unique": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "extensions",
|
||||
"keys": {
|
||||
"org_id": 1,
|
||||
"namespace": 1
|
||||
},
|
||||
"name": "extensions_org_id_namespace_idx",
|
||||
"unique": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"createCollection": "invitations",
|
||||
"validator": {
|
||||
"$jsonSchema": {
|
||||
"bsonType": "object",
|
||||
"required": [
|
||||
"_id",
|
||||
"version",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"org_id",
|
||||
"email",
|
||||
"role",
|
||||
"workspace_id",
|
||||
"token_hash",
|
||||
"expires_at",
|
||||
"invited_by"
|
||||
],
|
||||
"properties": {
|
||||
"_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"version": {
|
||||
"bsonType": "number"
|
||||
},
|
||||
"created_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"updated_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"org_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"email": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"role": {
|
||||
"bsonType": "string",
|
||||
"enum": ["viewer", "member", "admin", "owner"]
|
||||
},
|
||||
"workspace_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"workspace_role": {
|
||||
"bsonType": ["string", "null"],
|
||||
"enum": ["viewer", "editor", "admin"]
|
||||
},
|
||||
"token_hash": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"expires_at": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"accepted_at": {
|
||||
"bsonType": ["string", "null"]
|
||||
},
|
||||
"invited_by": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "invitations",
|
||||
"keys": {
|
||||
"org_id": 1,
|
||||
"token_hash": 1
|
||||
},
|
||||
"name": "invitations_org_id_token_hash_key",
|
||||
"unique": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "invitations",
|
||||
"keys": {
|
||||
"org_id": 1,
|
||||
"email": 1
|
||||
},
|
||||
"name": "invitations_org_id_email_idx",
|
||||
"unique": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "invitations",
|
||||
"keys": {
|
||||
"org_id": 1,
|
||||
"accepted_at": 1
|
||||
},
|
||||
"name": "invitations_org_id_accepted_at_idx",
|
||||
"unique": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"createCollection": "org_memberships",
|
||||
"validator": {
|
||||
"$jsonSchema": {
|
||||
"bsonType": "object",
|
||||
"required": ["_id", "version", "created_at", "updated_at", "org_id", "user_id", "role"],
|
||||
"properties": {
|
||||
"_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"version": {
|
||||
"bsonType": "number"
|
||||
},
|
||||
"created_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"updated_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"org_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"user_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"role": {
|
||||
"bsonType": "string",
|
||||
"enum": ["viewer", "member", "admin", "owner"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "org_memberships",
|
||||
"keys": {
|
||||
"org_id": 1,
|
||||
"user_id": 1
|
||||
},
|
||||
"name": "org_memberships_org_id_user_id_key",
|
||||
"unique": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "org_memberships",
|
||||
"keys": {
|
||||
"org_id": 1,
|
||||
"role": 1
|
||||
},
|
||||
"name": "org_memberships_org_id_role_idx",
|
||||
"unique": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"createCollection": "organizations",
|
||||
"validator": {
|
||||
"$jsonSchema": {
|
||||
"bsonType": "object",
|
||||
"required": ["_id", "version", "created_at", "updated_at", "slug", "name", "status", "settings"],
|
||||
"properties": {
|
||||
"_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"version": {
|
||||
"bsonType": "number"
|
||||
},
|
||||
"created_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"updated_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"slug": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"name": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"status": {
|
||||
"bsonType": "string",
|
||||
"enum": ["active", "suspended"]
|
||||
},
|
||||
"settings": {
|
||||
"bsonType": "object"
|
||||
},
|
||||
"branding": {
|
||||
"bsonType": ["object", "null"],
|
||||
"properties": {
|
||||
"displayName": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"primary": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"accent": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"logoLight": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"logoDark": {
|
||||
"bsonType": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "organizations",
|
||||
"keys": {
|
||||
"slug": 1
|
||||
},
|
||||
"name": "organizations_slug_key",
|
||||
"unique": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "organizations",
|
||||
"keys": {
|
||||
"status": 1
|
||||
},
|
||||
"name": "organizations_status_idx",
|
||||
"unique": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"createCollection": "projects",
|
||||
"validator": {
|
||||
"$jsonSchema": {
|
||||
"bsonType": "object",
|
||||
"required": [
|
||||
"_id",
|
||||
"version",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"org_id",
|
||||
"workspace_id",
|
||||
"slug",
|
||||
"name",
|
||||
"module_key"
|
||||
],
|
||||
"properties": {
|
||||
"_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"version": {
|
||||
"bsonType": "number"
|
||||
},
|
||||
"created_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"updated_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"org_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"workspace_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"slug": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"name": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"module_key": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"archived_at": {
|
||||
"bsonType": ["string", "null"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "projects",
|
||||
"keys": {
|
||||
"org_id": 1,
|
||||
"workspace_id": 1,
|
||||
"slug": 1
|
||||
},
|
||||
"name": "projects_org_id_workspace_id_slug_key",
|
||||
"unique": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "projects",
|
||||
"keys": {
|
||||
"org_id": 1,
|
||||
"workspace_id": 1,
|
||||
"archived_at": 1
|
||||
},
|
||||
"name": "projects_org_id_workspace_id_archived_at_idx",
|
||||
"unique": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"createCollection": "users",
|
||||
"validator": {
|
||||
"$jsonSchema": {
|
||||
"bsonType": "object",
|
||||
"required": [
|
||||
"_id",
|
||||
"version",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"issuer",
|
||||
"subject",
|
||||
"email",
|
||||
"display_name",
|
||||
"locale"
|
||||
],
|
||||
"properties": {
|
||||
"_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"version": {
|
||||
"bsonType": "number"
|
||||
},
|
||||
"created_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"updated_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"issuer": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"subject": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"email": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"display_name": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"locale": {
|
||||
"bsonType": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "users",
|
||||
"keys": {
|
||||
"issuer": 1,
|
||||
"subject": 1
|
||||
},
|
||||
"name": "users_issuer_subject_key",
|
||||
"unique": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "users",
|
||||
"keys": {
|
||||
"email": 1
|
||||
},
|
||||
"name": "users_email_idx",
|
||||
"unique": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"createCollection": "workspace_memberships",
|
||||
"validator": {
|
||||
"$jsonSchema": {
|
||||
"bsonType": "object",
|
||||
"required": ["_id", "version", "created_at", "updated_at", "org_id", "workspace_id", "user_id", "role"],
|
||||
"properties": {
|
||||
"_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"version": {
|
||||
"bsonType": "number"
|
||||
},
|
||||
"created_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"updated_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"org_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"workspace_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"user_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"role": {
|
||||
"bsonType": "string",
|
||||
"enum": ["viewer", "editor", "admin"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "workspace_memberships",
|
||||
"keys": {
|
||||
"org_id": 1,
|
||||
"workspace_id": 1,
|
||||
"user_id": 1
|
||||
},
|
||||
"name": "workspace_memberships_org_id_workspace_id_user_id_key",
|
||||
"unique": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "workspace_memberships",
|
||||
"keys": {
|
||||
"org_id": 1,
|
||||
"user_id": 1
|
||||
},
|
||||
"name": "workspace_memberships_org_id_user_id_idx",
|
||||
"unique": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"createCollection": "workspaces",
|
||||
"validator": {
|
||||
"$jsonSchema": {
|
||||
"bsonType": "object",
|
||||
"required": [
|
||||
"_id",
|
||||
"version",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"org_id",
|
||||
"slug",
|
||||
"name",
|
||||
"is_default",
|
||||
"visibility"
|
||||
],
|
||||
"properties": {
|
||||
"_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"version": {
|
||||
"bsonType": "number"
|
||||
},
|
||||
"created_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"updated_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"org_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"slug": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"name": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"is_default": {
|
||||
"bsonType": "bool"
|
||||
},
|
||||
"visibility": {
|
||||
"bsonType": "string",
|
||||
"enum": ["org", "restricted"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "workspaces",
|
||||
"keys": {
|
||||
"org_id": 1,
|
||||
"slug": 1
|
||||
},
|
||||
"name": "workspaces_org_id_slug_key",
|
||||
"unique": true
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,131 @@
|
||||
[
|
||||
{
|
||||
"createCollection": "files_file",
|
||||
"validator": {
|
||||
"$jsonSchema": {
|
||||
"bsonType": "object",
|
||||
"required": [
|
||||
"_id",
|
||||
"version",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"org_id",
|
||||
"workspace_id",
|
||||
"project_id",
|
||||
"status",
|
||||
"storage_key",
|
||||
"filename",
|
||||
"content_type",
|
||||
"uploaded_by"
|
||||
],
|
||||
"properties": {
|
||||
"_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"version": {
|
||||
"bsonType": "number"
|
||||
},
|
||||
"created_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"updated_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"org_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"workspace_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"project_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"status": {
|
||||
"bsonType": "string",
|
||||
"enum": ["pending", "stored", "deleting"]
|
||||
},
|
||||
"storage_key": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"filename": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"content_type": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"size": {
|
||||
"bsonType": ["number", "null"]
|
||||
},
|
||||
"sha256": {
|
||||
"bsonType": ["string", "null"]
|
||||
},
|
||||
"uploaded_by": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"stored_at": {
|
||||
"bsonType": ["string", "null"]
|
||||
},
|
||||
"upload_id": {
|
||||
"bsonType": ["string", "null"]
|
||||
},
|
||||
"declared_size": {
|
||||
"bsonType": ["number", "null"]
|
||||
},
|
||||
"part_size": {
|
||||
"bsonType": ["number", "null"]
|
||||
},
|
||||
"deleting_at": {
|
||||
"bsonType": ["string", "null"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "files_file",
|
||||
"keys": {
|
||||
"org_id": 1,
|
||||
"workspace_id": 1,
|
||||
"project_id": 1,
|
||||
"storage_key": 1
|
||||
},
|
||||
"name": "files_file_org_id_workspace_id_project_id_storage_key_key",
|
||||
"unique": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "files_file",
|
||||
"keys": {
|
||||
"org_id": 1,
|
||||
"workspace_id": 1,
|
||||
"project_id": 1,
|
||||
"status": 1
|
||||
},
|
||||
"name": "files_file_org_id_workspace_id_project_id_status_idx",
|
||||
"unique": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "files_file",
|
||||
"keys": {
|
||||
"org_id": 1,
|
||||
"workspace_id": 1,
|
||||
"project_id": 1,
|
||||
"sha256": 1
|
||||
},
|
||||
"name": "files_file_org_id_workspace_id_project_id_sha256_idx",
|
||||
"unique": false
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,164 @@
|
||||
[
|
||||
{
|
||||
"createCollection": "proposals",
|
||||
"validator": {
|
||||
"$jsonSchema": {
|
||||
"bsonType": "object",
|
||||
"required": [
|
||||
"_id",
|
||||
"version",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"org_id",
|
||||
"workspace_id",
|
||||
"project_id",
|
||||
"status",
|
||||
"target_key",
|
||||
"change",
|
||||
"evidence",
|
||||
"model",
|
||||
"prompt_version",
|
||||
"created_by"
|
||||
],
|
||||
"properties": {
|
||||
"_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"version": {
|
||||
"bsonType": "number"
|
||||
},
|
||||
"created_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"updated_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"org_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"workspace_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"project_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"status": {
|
||||
"bsonType": "string",
|
||||
"enum": ["pending", "approved", "rejected"]
|
||||
},
|
||||
"target_key": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"target_record_id": {
|
||||
"bsonType": ["string", "null"]
|
||||
},
|
||||
"written_record_id": {
|
||||
"bsonType": ["string", "null"]
|
||||
},
|
||||
"change": {
|
||||
"bsonType": "object"
|
||||
},
|
||||
"evidence": {
|
||||
"bsonType": "array",
|
||||
"items": {
|
||||
"bsonType": "object",
|
||||
"required": ["fileId"],
|
||||
"properties": {
|
||||
"fileId": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"page": {
|
||||
"bsonType": "number"
|
||||
},
|
||||
"blockId": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"box": {
|
||||
"bsonType": "object",
|
||||
"required": ["x", "y", "width", "height"],
|
||||
"properties": {
|
||||
"x": {
|
||||
"bsonType": "number"
|
||||
},
|
||||
"y": {
|
||||
"bsonType": "number"
|
||||
},
|
||||
"width": {
|
||||
"bsonType": "number"
|
||||
},
|
||||
"height": {
|
||||
"bsonType": "number"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"quote": {
|
||||
"bsonType": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"model": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"prompt_version": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"created_by": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"edited_by": {
|
||||
"bsonType": ["string", "null"]
|
||||
},
|
||||
"edited_at": {
|
||||
"bsonType": ["string", "null"]
|
||||
},
|
||||
"decided_by": {
|
||||
"bsonType": ["string", "null"]
|
||||
},
|
||||
"decided_at": {
|
||||
"bsonType": ["string", "null"]
|
||||
},
|
||||
"reason": {
|
||||
"bsonType": ["string", "null"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "proposals",
|
||||
"keys": {
|
||||
"org_id": 1,
|
||||
"workspace_id": 1,
|
||||
"project_id": 1,
|
||||
"status": 1
|
||||
},
|
||||
"name": "proposals_org_id_workspace_id_project_id_status_idx",
|
||||
"unique": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "proposals",
|
||||
"keys": {
|
||||
"org_id": 1,
|
||||
"workspace_id": 1,
|
||||
"project_id": 1,
|
||||
"target_key": 1,
|
||||
"target_record_id": 1
|
||||
},
|
||||
"name": "proposals_org_id_workspace_id_project_id_target_key_target_record_id_idx",
|
||||
"unique": false
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,63 @@
|
||||
[
|
||||
{
|
||||
"createCollection": "app_user_identity",
|
||||
"validator": {
|
||||
"$jsonSchema": {
|
||||
"bsonType": "object",
|
||||
"required": ["_id", "version", "created_at", "updated_at", "issuer", "subject", "user_id"],
|
||||
"properties": {
|
||||
"_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"version": {
|
||||
"bsonType": "number"
|
||||
},
|
||||
"created_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"updated_at": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"issuer": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"subject": {
|
||||
"bsonType": "string"
|
||||
},
|
||||
"user_id": {
|
||||
"bsonType": "string",
|
||||
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
},
|
||||
"migration_id": {
|
||||
"bsonType": ["string", "null"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "app_user_identity",
|
||||
"keys": {
|
||||
"issuer": 1,
|
||||
"subject": 1
|
||||
},
|
||||
"name": "app_user_identity_issuer_subject_key",
|
||||
"unique": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"createIndex": {
|
||||
"collection": "app_user_identity",
|
||||
"keys": {
|
||||
"user_id": 1
|
||||
},
|
||||
"name": "app_user_identity_user_id_idx",
|
||||
"unique": false
|
||||
}
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user