This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
<!-- SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0 -->
|
||||
# The mariadb profile
|
||||
|
||||
**Status (source review 2026-10-21): adapter and migration assets, not a deployable
|
||||
generated app profile.** The CLI accepts MariaDB pruning, but only the Convex
|
||||
selection path rewrites the root runtime/deployment composition. The web/worker
|
||||
roots have no MySQL composition, and the previously described profile config
|
||||
file is absent. The platform injects `DATABASE_URL`; these draft assets still
|
||||
name `MARIADB_URL`, so their variable contract also needs reconciliation.
|
||||
The tables and generated-app steps below describe the target design. Adapter
|
||||
and migration-engine tests do not establish a generated application deployment.
|
||||
|
||||
|
||||
The persistence profile for an app whose primary store is MariaDB instead of Postgres
|
||||
(spec §5.1): the same procedures, the same modules, the same migrations discipline, on the
|
||||
Kysely MySQL dialect (`@conusai-kit/data-kysely/mysql`) with jobs on BullMQ over Valkey
|
||||
(`@conusai-kit/jobs-bullmq`).
|
||||
|
||||
| | postgres (default) | mariadb (this profile) |
|
||||
|---|---|---|
|
||||
| Primary store | Postgres 18 | MariaDB LTS |
|
||||
| Data adapter | `@conusai-kit/data-kysely` | `@conusai-kit/data-kysely/mysql` |
|
||||
| Jobs | pg-boss (Postgres) | BullMQ on Valkey (`@conusai-kit/jobs-bullmq`) |
|
||||
| Tenant wall | repository predicate + RLS (three roles, AT-D20) | repository predicate alone — MariaDB has no RLS |
|
||||
| Links | `postgres`, `identity` | `mariadb`, `redis`, `identity` |
|
||||
| Process env | `POSTGRES_URL`, `POSTGRES_READER_URL`, `POSTGRES_MIGRATE_URL` | `MARIADB_URL`, `REDIS_URL` |
|
||||
|
||||
## What this folder carries
|
||||
|
||||
- `conusai.json` — the profile's deployment contract: the same three services, links
|
||||
`mariadb` + `redis` + `identity`. There is no `mariadb.migrate` flag: the three-role split it
|
||||
declares on Postgres (data-services DS21) exists to make row-level security bind, and MariaDB
|
||||
has none, so every process holds the one `MARIADB_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
|
||||
`mariadb:lts` and `valkey/valkey:9-alpine`, the images the platform's catalog offers.
|
||||
- `migrations/` — the kernel tables (tenancy, sign-in, files, proposals, outbox, idempotency
|
||||
keys) as MariaDB DDL, generated by `mysqlSchemaStatements` from the same entity definitions as
|
||||
the postgres files and committed, forward-only. A module's own MariaDB migrations live with the
|
||||
module: `modules/<id>/adapters/kysely/mysql/migrations/`, declared in its manifest as
|
||||
`migrations: { postgres: "migrations", mariadb: "adapters/kysely/mysql/migrations" }`.
|
||||
|
||||
## Target generated-app changes (not wired)
|
||||
|
||||
The profile is chosen at generation time (`.conusai/template.json` `profile`), and
|
||||
`kit template:prune --profile mariadb` removes the other dialects. Concretely:
|
||||
|
||||
1. `config/src/env.ts` reads `MARIADB_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 `createMysqlDataSource` (Kysely `MysqlDialect` + `mysql2`)
|
||||
and the worker's queue is `createBullmqJobQueue`/`createBullmqWorker` over `REDIS_URL`.
|
||||
3. The migrate job runs `runMysqlMigrationsFromEnv` over `profiles/mariadb/migrations/` (moved to
|
||||
`migrations/mariadb/`) and the modules' `adapters/kysely/mysql/migrations/`.
|
||||
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 MariaDB
|
||||
schema is its own numbered SQL folder, reviewed like any migration.
|
||||
|
||||
## Proof
|
||||
|
||||
- `@conusai-kit/data-kysely`'s MySQL dialect passes the shared repository and capability contract
|
||||
suites against `mariadb:lts` in testcontainers — the tenant predicate is the wall, and the
|
||||
contract is what proves it.
|
||||
- `@conusai-kit/jobs-bullmq` passes the shared JobQueue contract against `valkey/valkey:9` in
|
||||
testcontainers.
|
||||
- `scripts/vendor/test-template.sh app --profile mariadb` runs the template's gate and then
|
||||
applies this folder's and the modules' MariaDB migrations to a real MariaDB LTS container, so
|
||||
the committed DDL is proven against the engine, not just generated.
|
||||
@@ -0,0 +1,120 @@
|
||||
# SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
|
||||
# Local development for the mariadb profile: MariaDB 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`).
|
||||
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:
|
||||
mariadb:
|
||||
image: mariadb:lts
|
||||
environment:
|
||||
MARIADB_ROOT_PASSWORD: mariadb
|
||||
MARIADB_DATABASE: appdev
|
||||
volumes:
|
||||
- mariadb-data:/var/lib/mysql
|
||||
# Published on loopback only, for `pnpm dev`, which runs the processes on this machine.
|
||||
ports: ["127.0.0.1:${DEV_MARIADB_PORT:-53307}:3306"]
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "mariadb-admin ping -h 127.0.0.1 -uroot -pmariadb --silent"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 20
|
||||
restart: unless-stopped
|
||||
|
||||
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:
|
||||
mariadb:
|
||||
condition: service_healthy
|
||||
|
||||
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}
|
||||
MARIADB_URL: ${MARIADB_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:
|
||||
mariadb:
|
||||
condition: service_healthy
|
||||
valkey:
|
||||
condition: service_healthy
|
||||
migrate:
|
||||
condition: service_completed_successfully
|
||||
seed:
|
||||
condition: service_completed_successfully
|
||||
platform:
|
||||
condition: service_healthy
|
||||
|
||||
worker:
|
||||
environment: *development
|
||||
depends_on:
|
||||
mariadb:
|
||||
condition: service_healthy
|
||||
valkey:
|
||||
condition: service_healthy
|
||||
migrate:
|
||||
condition: service_completed_successfully
|
||||
platform:
|
||||
condition: service_healthy
|
||||
|
||||
volumes:
|
||||
mariadb-data:
|
||||
valkey-data:
|
||||
@@ -0,0 +1,152 @@
|
||||
# SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
|
||||
# The mariadb 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).
|
||||
#
|
||||
# MariaDB has no row-level security, so there is no owner/runtime/reader split to enforce it
|
||||
# with: every process holds the one MARIADB_URL the platform injects for a linked MariaDB, and
|
||||
# the tenant wall is the repository predicate, proven by the kit's contract suite
|
||||
# (@conusai-kit/data-kysely's MySQL dialect runs it against mariadb:lts). Jobs are BullMQ on the
|
||||
# linked Valkey (REDIS_URL).
|
||||
#
|
||||
# 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:-}
|
||||
MARIADB_URL: ${MARIADB_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_AUDIENCE: ${OIDC_AUDIENCE:-}
|
||||
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:-}
|
||||
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_PUBLIC_URL: ${CONUSAI_PUBLIC_URL}
|
||||
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:-}
|
||||
DOCUMENTS_EXCLUDED_PAGE_CLASSES: ${DOCUMENTS_EXCLUDED_PAGE_CLASSES:-}
|
||||
MARIADB_URL: ${MARIADB_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}
|
||||
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:-}
|
||||
# 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).
|
||||
MARIADB_URL: ${MARIADB_URL}
|
||||
restart: "no"
|
||||
init: true
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: "1.0"
|
||||
memory: 512M
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"$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": "mariadb"
|
||||
},
|
||||
{
|
||||
"type": "redis"
|
||||
},
|
||||
{
|
||||
"type": "identity"
|
||||
}
|
||||
],
|
||||
"token": {
|
||||
"permissions": ["ocr:use", "ai:execute", "usage:write", "guides:runtime", "support:widget-sessions", "privacy:subjects"]
|
||||
},
|
||||
"previews": {
|
||||
"enabled": true,
|
||||
"size": "small"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
-- SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
|
||||
create table `outbox` (
|
||||
`id` char(36) primary key,
|
||||
`org_id` char(36) not null,
|
||||
`name` text not null,
|
||||
`payload` json not null,
|
||||
`created_at` datetime(6) not null,
|
||||
`attempts` integer not null,
|
||||
`published_at` datetime(6),
|
||||
`last_error` text,
|
||||
`deferrals` integer not null default 0,
|
||||
`deferred_since` datetime(6),
|
||||
`deferred_until` datetime(6)
|
||||
) engine=InnoDB default charset=utf8mb4;
|
||||
|
||||
create index `outbox_pending_idx` on `outbox` (`created_at`);
|
||||
|
||||
create table `idempotency_keys` (
|
||||
`org_id` char(36) not null,
|
||||
-- Not null, with the zero uuid where a scope has no workspace or project: a primary key
|
||||
-- ignores a row whose column is NULL, and the key would stop being unique.
|
||||
`workspace_id` char(36) not null,
|
||||
`project_id` char(36) not null,
|
||||
`procedure` varchar(255) not null,
|
||||
`key` varchar(255) not null,
|
||||
-- The response may itself be the JSON value null, so "finished" is a column of its own
|
||||
-- rather than a non-null response. Null while the transaction that claimed this key is
|
||||
-- running; a second caller's insert blocks on the key until that transaction ends.
|
||||
`response` json,
|
||||
`completed_at` datetime(6),
|
||||
`created_at` datetime(6) not null,
|
||||
primary key (`org_id`, `workspace_id`, `project_id`, `procedure`, `key`)
|
||||
) engine=InnoDB default charset=utf8mb4;
|
||||
|
||||
create table `auth_api_keys` (
|
||||
`id` char(36) primary key,
|
||||
`version` integer not null,
|
||||
`created_at` datetime(6) not null,
|
||||
`updated_at` datetime(6) not null,
|
||||
`org_id` char(36) not null,
|
||||
`name` text not null,
|
||||
`token_hash` text not null,
|
||||
`prefix` text not null,
|
||||
`user_id` char(36) not null,
|
||||
`expires_at` text,
|
||||
`revoked_at` text
|
||||
) engine=InnoDB default charset=utf8mb4;
|
||||
|
||||
alter table `auth_api_keys` add constraint `auth_api_keys_org_id_token_hash_key` unique (`org_id`, `token_hash`);
|
||||
|
||||
create index `auth_api_keys_org_id_user_id_idx` on `auth_api_keys` (`org_id`, `user_id`);
|
||||
|
||||
create index `auth_api_keys_org_id_prefix_idx` on `auth_api_keys` (`org_id`, `prefix`(191));
|
||||
|
||||
create table `auth_sessions` (
|
||||
`id` char(36) primary key,
|
||||
`version` integer not null,
|
||||
`created_at` datetime(6) not null,
|
||||
`updated_at` datetime(6) not null,
|
||||
`user_id` char(36) not null,
|
||||
`issuer` text not null,
|
||||
`subject` text not null,
|
||||
`handle_hash` text not null,
|
||||
`tokens` text not null,
|
||||
`access_token_expires_at` text not null,
|
||||
`last_seen_at` text not null,
|
||||
`absolute_expires_at` text not null,
|
||||
`revoked_at` text
|
||||
) engine=InnoDB default charset=utf8mb4;
|
||||
|
||||
alter table `auth_sessions` add constraint `auth_sessions_handle_hash_key` unique (`handle_hash`);
|
||||
|
||||
create index `auth_sessions_user_id_idx` on `auth_sessions` (`user_id`);
|
||||
|
||||
create index `auth_sessions_absolute_expires_at_idx` on `auth_sessions` (`absolute_expires_at`(191));
|
||||
|
||||
create table `extensions` (
|
||||
`id` char(36) primary key,
|
||||
`version` integer not null,
|
||||
`created_at` datetime(6) not null,
|
||||
`updated_at` datetime(6) not null,
|
||||
`org_id` char(36) not null,
|
||||
`subject_type` text not null,
|
||||
`subject_id` char(36) not null,
|
||||
`namespace` text not null,
|
||||
`payload` json not null,
|
||||
`payload_version` integer not null
|
||||
) engine=InnoDB default charset=utf8mb4;
|
||||
|
||||
alter table `extensions` add constraint `extensions_org_id_subject_type_subject_id_namespace_key` unique (`org_id`, `subject_type`, `subject_id`, `namespace`);
|
||||
|
||||
create index `extensions_org_id_namespace_idx` on `extensions` (`org_id`, `namespace`(191));
|
||||
|
||||
create table `invitations` (
|
||||
`id` char(36) primary key,
|
||||
`version` integer not null,
|
||||
`created_at` datetime(6) not null,
|
||||
`updated_at` datetime(6) not null,
|
||||
`org_id` char(36) not null,
|
||||
`email` text not null,
|
||||
`role` text not null,
|
||||
`workspace_id` char(36),
|
||||
`workspace_role` text,
|
||||
`token_hash` text not null,
|
||||
`expires_at` text not null,
|
||||
`accepted_at` text,
|
||||
`invited_by` char(36) not null
|
||||
) engine=InnoDB default charset=utf8mb4;
|
||||
|
||||
alter table `invitations` add constraint `invitations_org_id_token_hash_key` unique (`org_id`, `token_hash`);
|
||||
|
||||
create index `invitations_org_id_email_idx` on `invitations` (`org_id`, `email`(191));
|
||||
|
||||
create index `invitations_org_id_accepted_at_idx` on `invitations` (`org_id`, `accepted_at`(191));
|
||||
|
||||
create table `org_memberships` (
|
||||
`id` char(36) primary key,
|
||||
`version` integer not null,
|
||||
`created_at` datetime(6) not null,
|
||||
`updated_at` datetime(6) not null,
|
||||
`org_id` char(36) not null,
|
||||
`user_id` char(36) not null,
|
||||
`role` text not null
|
||||
) engine=InnoDB default charset=utf8mb4;
|
||||
|
||||
alter table `org_memberships` add constraint `org_memberships_org_id_user_id_key` unique (`org_id`, `user_id`);
|
||||
|
||||
create index `org_memberships_org_id_role_idx` on `org_memberships` (`org_id`, `role`(191));
|
||||
|
||||
create table `organizations` (
|
||||
`id` char(36) primary key,
|
||||
`version` integer not null,
|
||||
`created_at` datetime(6) not null,
|
||||
`updated_at` datetime(6) not null,
|
||||
`slug` text not null,
|
||||
`name` text not null,
|
||||
`status` text not null,
|
||||
`settings` json not null,
|
||||
`branding` json
|
||||
) engine=InnoDB default charset=utf8mb4;
|
||||
|
||||
alter table `organizations` add constraint `organizations_slug_key` unique (`slug`);
|
||||
|
||||
create index `organizations_status_idx` on `organizations` (`status`(191));
|
||||
|
||||
create table `projects` (
|
||||
`id` char(36) primary key,
|
||||
`version` integer not null,
|
||||
`created_at` datetime(6) not null,
|
||||
`updated_at` datetime(6) not null,
|
||||
`org_id` char(36) not null,
|
||||
`workspace_id` char(36) not null,
|
||||
`slug` text not null,
|
||||
`name` text not null,
|
||||
`module_key` text not null,
|
||||
`archived_at` text
|
||||
) engine=InnoDB default charset=utf8mb4;
|
||||
|
||||
alter table `projects` add constraint `projects_org_id_workspace_id_slug_key` unique (`org_id`, `workspace_id`, `slug`);
|
||||
|
||||
create index `projects_org_id_workspace_id_archived_at_idx` on `projects` (`org_id`, `workspace_id`, `archived_at`(191));
|
||||
|
||||
create table `users` (
|
||||
`id` char(36) primary key,
|
||||
`version` integer not null,
|
||||
`created_at` datetime(6) not null,
|
||||
`updated_at` datetime(6) not null,
|
||||
`issuer` text not null,
|
||||
`subject` text not null,
|
||||
`email` text not null,
|
||||
`display_name` text not null,
|
||||
`locale` text not null
|
||||
) engine=InnoDB default charset=utf8mb4;
|
||||
|
||||
alter table `users` add constraint `users_issuer_subject_key` unique (`issuer`, `subject`);
|
||||
|
||||
create index `users_email_idx` on `users` (`email`(191));
|
||||
|
||||
create table `workspace_memberships` (
|
||||
`id` char(36) primary key,
|
||||
`version` integer not null,
|
||||
`created_at` datetime(6) not null,
|
||||
`updated_at` datetime(6) not null,
|
||||
`org_id` char(36) not null,
|
||||
`workspace_id` char(36) not null,
|
||||
`user_id` char(36) not null,
|
||||
`role` text not null
|
||||
) engine=InnoDB default charset=utf8mb4;
|
||||
|
||||
alter table `workspace_memberships` add constraint `workspace_memberships_org_id_workspace_id_user_id_key` unique (`org_id`, `workspace_id`, `user_id`);
|
||||
|
||||
create index `workspace_memberships_org_id_user_id_idx` on `workspace_memberships` (`org_id`, `user_id`);
|
||||
|
||||
create table `workspaces` (
|
||||
`id` char(36) primary key,
|
||||
`version` integer not null,
|
||||
`created_at` datetime(6) not null,
|
||||
`updated_at` datetime(6) not null,
|
||||
`org_id` char(36) not null,
|
||||
`slug` text not null,
|
||||
`name` text not null,
|
||||
`is_default` boolean not null,
|
||||
`visibility` text not null
|
||||
) engine=InnoDB default charset=utf8mb4;
|
||||
|
||||
alter table `workspaces` add constraint `workspaces_org_id_slug_key` unique (`org_id`, `slug`);
|
||||
@@ -0,0 +1,28 @@
|
||||
-- SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
|
||||
create table `files_file` (
|
||||
`id` char(36) primary key,
|
||||
`version` integer not null,
|
||||
`created_at` datetime(6) not null,
|
||||
`updated_at` datetime(6) not null,
|
||||
`org_id` char(36) not null,
|
||||
`workspace_id` char(36) not null,
|
||||
`project_id` char(36) not null,
|
||||
`status` text not null,
|
||||
`storage_key` text not null,
|
||||
`filename` text not null,
|
||||
`content_type` text not null,
|
||||
`size` integer,
|
||||
`sha256` text,
|
||||
`uploaded_by` char(36) not null,
|
||||
`stored_at` text,
|
||||
`upload_id` text,
|
||||
`declared_size` integer,
|
||||
`part_size` integer,
|
||||
`deleting_at` text
|
||||
) engine=InnoDB default charset=utf8mb4;
|
||||
|
||||
alter table `files_file` add constraint `files_file_org_id_workspace_id_project_id_storage_key_key` unique (`org_id`, `workspace_id`, `project_id`, `storage_key`);
|
||||
|
||||
create index `files_file_org_id_workspace_id_project_id_status_idx` on `files_file` (`org_id`, `workspace_id`, `project_id`, `status`(191));
|
||||
|
||||
create index `files_file_org_id_workspace_id_project_id_sha256_idx` on `files_file` (`org_id`, `workspace_id`, `project_id`, `sha256`(191));
|
||||
@@ -0,0 +1,28 @@
|
||||
-- SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
|
||||
create table `proposals` (
|
||||
`id` char(36) primary key,
|
||||
`version` integer not null,
|
||||
`created_at` datetime(6) not null,
|
||||
`updated_at` datetime(6) not null,
|
||||
`org_id` char(36) not null,
|
||||
`workspace_id` char(36) not null,
|
||||
`project_id` char(36) not null,
|
||||
`status` text not null,
|
||||
`target_key` text not null,
|
||||
`target_record_id` text,
|
||||
`written_record_id` text,
|
||||
`change` json not null,
|
||||
`evidence` json not null,
|
||||
`model` text not null,
|
||||
`prompt_version` text not null,
|
||||
`created_by` text not null,
|
||||
`edited_by` text,
|
||||
`edited_at` text,
|
||||
`decided_by` text,
|
||||
`decided_at` text,
|
||||
`reason` text
|
||||
) engine=InnoDB default charset=utf8mb4;
|
||||
|
||||
create index `proposals_org_id_workspace_id_project_id_status_idx` on `proposals` (`org_id`, `workspace_id`, `project_id`, `status`(191));
|
||||
|
||||
create index `proposals_org_id_workspace_id_project_id_target_key_tar_25412770` on `proposals` (`org_id`, `workspace_id`, `project_id`, `target_key`(191), `target_record_id`(191));
|
||||
@@ -0,0 +1,36 @@
|
||||
-- SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
|
||||
create table `app_user_identity` (
|
||||
`id` char(36) primary key,
|
||||
`version` integer not null,
|
||||
`created_at` datetime(6) not null,
|
||||
`updated_at` datetime(6) not null,
|
||||
`issuer` varchar(255) not null,
|
||||
`subject` varchar(255) not null,
|
||||
`user_id` char(36) not null,
|
||||
`migration_id` varchar(255)
|
||||
) engine=InnoDB default charset=utf8mb4;
|
||||
|
||||
alter table `app_user_identity` add constraint `app_user_identity_issuer_subject_key` unique (`issuer`, `subject`);
|
||||
|
||||
create index `app_user_identity_user_id_idx` on `app_user_identity` (`user_id`);
|
||||
|
||||
insert into `app_user_identity` (
|
||||
`id`,
|
||||
`version`,
|
||||
`created_at`,
|
||||
`updated_at`,
|
||||
`issuer`,
|
||||
`subject`,
|
||||
`user_id`,
|
||||
`migration_id`
|
||||
)
|
||||
select
|
||||
`id`,
|
||||
1,
|
||||
`created_at`,
|
||||
`updated_at`,
|
||||
`issuer`,
|
||||
`subject`,
|
||||
`id`,
|
||||
'legacy-users-issuer-subject-v1'
|
||||
from `users`;
|
||||
Reference in New Issue
Block a user