@percepta/create 3.6.2 → 3.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/README.md +37 -6
  2. package/dist/{git-ops-C2CIjuce.js → git-ops-BD7JNnal.js} +1 -1
  3. package/dist/{git-ops-C2CIjuce.js.map → git-ops-BD7JNnal.js.map} +1 -1
  4. package/dist/github-RCIMUq70.js +131 -0
  5. package/dist/github-RCIMUq70.js.map +1 -0
  6. package/dist/index.js +63 -122
  7. package/dist/index.js.map +1 -1
  8. package/dist/{init-sI9aIrkU.js → init-COp0nGdk.js} +4 -2
  9. package/dist/{init-sI9aIrkU.js.map → init-COp0nGdk.js.map} +1 -1
  10. package/dist/manifest-CqIDnbgs.js +58 -0
  11. package/dist/manifest-CqIDnbgs.js.map +1 -0
  12. package/dist/register-app-C7ZBpAaZ.js +103 -0
  13. package/dist/register-app-C7ZBpAaZ.js.map +1 -0
  14. package/dist/register-os-blueprint-DGjBUZYa.js +90 -0
  15. package/dist/register-os-blueprint-DGjBUZYa.js.map +1 -0
  16. package/dist/{status-CKe4aKso.js → status-BXYaQ4a2.js} +3 -3
  17. package/dist/{status-CKe4aKso.js.map → status-BXYaQ4a2.js.map} +1 -1
  18. package/dist/{sync-D1vkoofl.js → sync-BayU4w1j.js} +3 -3
  19. package/dist/{sync-D1vkoofl.js.map → sync-BayU4w1j.js.map} +1 -1
  20. package/dist/template-versions-CEIP9vhl.js +35 -0
  21. package/dist/template-versions-CEIP9vhl.js.map +1 -0
  22. package/dist/{upstream-gUHLWSR1.js → upstream-CZEzLrS4.js} +3 -3
  23. package/dist/{upstream-gUHLWSR1.js.map → upstream-CZEzLrS4.js.map} +1 -1
  24. package/dist/validate-dssldJAj.js +14 -0
  25. package/dist/validate-dssldJAj.js.map +1 -0
  26. package/package.json +1 -1
  27. package/template-versions.json +2 -2
  28. package/templates/infra/os.blueprint.yaml.template +138 -0
  29. package/templates/monorepo/README.md +41 -3
  30. package/templates/monorepo/auth/README.md +6 -3
  31. package/templates/monorepo/auth/package.json +2 -4
  32. package/templates/monorepo/auth/src/config/database.ts +1 -1
  33. package/templates/{webapp → monorepo}/docker-compose.yml +2 -2
  34. package/templates/monorepo/package.json.template +5 -2
  35. package/templates/monorepo/scripts/setup-local-databases.mjs +183 -0
  36. package/templates/webapp/AGENTS.md +13 -20
  37. package/templates/webapp/README.md +32 -36
  38. package/templates/webapp/agent-skills/database.md +21 -21
  39. package/templates/webapp/agent-skills/langfuse.md +7 -7
  40. package/templates/webapp/agent-skills/llm.md +4 -2
  41. package/templates/webapp/agent-skills/oneshot.md +7 -6
  42. package/templates/webapp/agent-skills/ryvn.md +12 -16
  43. package/templates/webapp/deploy/README.md +10 -51
  44. package/templates/webapp/drizzle.config.ts +2 -23
  45. package/templates/webapp/env.example.template +8 -14
  46. package/templates/webapp/package.json.template +5 -12
  47. package/templates/webapp/scripts/start.sh +12 -16
  48. package/templates/webapp/src/config/getEnvConfig.ts +4 -10
  49. package/templates/webapp/src/drizzle/db.ts +6 -21
  50. package/templates/webapp/src/startup-checks.ts +28 -7
  51. package/templates/monorepo/auth/scripts/setup-database.ts +0 -11
  52. package/templates/webapp/.github/workflows/__APP_NAME__-terraform-ryvn-release.yaml +0 -92
  53. package/templates/webapp/agent-skills/deploy.md +0 -92
  54. package/templates/webapp/deploy/ryvn/__APP_NAME__-terraform.service.yaml +0 -10
  55. package/templates/webapp/deploy/ryvn/environments/percepta-test/installations/__APP_NAME__-terraform.env.percepta-test.serviceinstallation.yaml +0 -11
  56. package/templates/webapp/deploy/ryvn/environments/percepta-test/installations/__APP_NAME__.env.percepta-test.serviceinstallation.yaml +0 -154
  57. package/templates/webapp/terraform/README.md +0 -147
  58. package/templates/webapp/terraform/deploy.sh +0 -97
  59. package/templates/webapp/terraform/main.tf +0 -101
  60. package/templates/webapp/terraform/modules/cloudtrail/main.tf +0 -27
  61. package/templates/webapp/terraform/modules/cloudtrail/outputs.tf +0 -10
  62. package/templates/webapp/terraform/modules/cloudtrail/variables.tf +0 -15
  63. package/templates/webapp/terraform/modules/networking/main.tf +0 -118
  64. package/templates/webapp/terraform/modules/networking/outputs.tf +0 -38
  65. package/templates/webapp/terraform/modules/networking/variables.tf +0 -24
  66. package/templates/webapp/terraform/modules/rds/main.tf +0 -227
  67. package/templates/webapp/terraform/modules/rds/outputs.tf +0 -73
  68. package/templates/webapp/terraform/modules/rds/variables.tf +0 -61
  69. package/templates/webapp/terraform/modules/s3-logging/main.tf +0 -148
  70. package/templates/webapp/terraform/modules/s3-logging/outputs.tf +0 -10
  71. package/templates/webapp/terraform/modules/s3-logging/variables.tf +0 -16
  72. package/templates/webapp/terraform/modules/secrets/main.tf +0 -39
  73. package/templates/webapp/terraform/modules/secrets/outputs.tf +0 -9
  74. package/templates/webapp/terraform/modules/secrets/variables.tf +0 -51
  75. package/templates/webapp/terraform/outputs.tf +0 -102
  76. package/templates/webapp/terraform/providers.tf +0 -32
  77. package/templates/webapp/terraform/schema/main.tf +0 -4
  78. package/templates/webapp/terraform/schema/outputs.tf +0 -9
  79. package/templates/webapp/terraform/schema/variables.tf +0 -19
  80. package/templates/webapp/terraform/schema/versions.tf +0 -38
  81. package/templates/webapp/terraform/terraform.tfvars.example +0 -65
  82. package/templates/webapp/terraform/variables.tf +0 -129
@@ -38,11 +38,9 @@ export * from "./documents";
38
38
  pnpm db:generate
39
39
  ```
40
40
 
41
- This creates a new SQL migration file and normalizes generated foreign key
42
- references so they stay schema-relative when `DATABASE_SCHEMA` is set in
43
- `percepta-test`. **Review the generated SQL** Drizzle generates it
44
- automatically but you should verify it's correct, especially for new foreign
45
- keys and destructive changes.
41
+ This creates a new SQL migration file and normalizes generated SQL. **Review
42
+ the generated SQL** Drizzle generates it automatically but you should verify
43
+ it's correct, especially for new foreign keys and destructive changes.
46
44
 
47
45
  ### 4. Apply the migration
48
46
 
@@ -95,21 +93,25 @@ If `createTransaction` is called while already inside a transaction, it reuses t
95
93
 
96
94
  ## Running PostgreSQL Locally
97
95
 
98
- ### Start with Docker Compose
96
+ ### Start with root setup
99
97
 
100
98
  ```bash
101
- pnpm docker:up
99
+ pnpm run setup
102
100
  ```
103
101
 
104
- This starts PostgreSQL 16 on port **5434** (not the default 5432, to avoid conflicts).
102
+ This delegates to the monorepo root. Root setup starts PostgreSQL 16 on port
103
+ **5434** and SpiceDB on **50051**, creates the shared auth database plus each
104
+ app database discovered from `packages/*/.env.local`, then runs migrations and
105
+ seeds.
105
106
 
106
- ### Create the database and run migrations
107
+ ### Run migrations
107
108
 
108
109
  ```bash
109
- pnpm db:setup-and-migrate
110
+ pnpm db:migrate
110
111
  ```
111
112
 
112
- This creates the database if it doesn't exist and applies all pending migrations.
113
+ This applies all pending migrations. Database creation is owned by the local
114
+ infrastructure setup, not by the app migration command.
113
115
 
114
116
  ### Inspect the database
115
117
 
@@ -119,27 +121,25 @@ pnpm db:studio
119
121
 
120
122
  Opens Drizzle Studio in the browser — a visual database explorer.
121
123
 
122
- ### Stop PostgreSQL
124
+ ### Stop local services
123
125
 
124
126
  ```bash
125
- pnpm docker:down
127
+ pnpm --dir ../.. run docker:down
126
128
  ```
127
129
 
128
130
  ## Environment Variables
129
131
 
130
132
  | Variable | Default | Description |
131
133
  |----------|---------|-------------|
132
- | `DATABASE_HOST` | `localhost` | PostgreSQL host |
133
- | `DATABASE_PORT` | `5434` | PostgreSQL port |
134
- | `DATABASE_USERNAME` | `postgres` | Database user |
135
- | `DATABASE_PASSWORD` | `postgres` | Database password |
136
- | `DATABASE_NAME` | `__DB_NAME__` | Database name |
137
- | `DATABASE_SCHEMA` | - | Optional Postgres schema/search path |
138
- | `DATABASE_USE_SSL` | `false` | Enable SSL connections |
134
+ | `DATABASE_URL` | `postgresql://postgres:postgres@localhost:5434/__DB_NAME__` | App PostgreSQL connection URL |
135
+
136
+ Shared auth data belongs to the customer monorepo auth package. Deployed apps
137
+ should receive `AUTH_DATABASE_URL` from the monorepo auth Secret; do not reuse
138
+ `DATABASE_URL` for auth.
139
139
 
140
140
  ## Key Concepts
141
141
 
142
142
  - **Schemas are TypeScript, migrations are SQL.** You define tables in TS, then `pnpm db:generate` creates the SQL diff. Never hand-write migration SQL.
143
143
  - **DatabaseService is a singleton.** Call `DatabaseService.create()` anywhere — it always returns the same instance with the same connection pool.
144
144
  - **Transaction propagation is automatic.** Code inside `createTransaction` gets a transaction; code outside gets the raw connection. `getDatabase()` returns whichever is active.
145
- - **Port 5434.** The local Docker Compose uses port 5434 to avoid conflicting with any system PostgreSQL on 5432.
145
+ - **Root-owned local infra.** The monorepo root Docker Compose uses port 5434 to avoid conflicting with any system PostgreSQL on 5432.
@@ -60,11 +60,11 @@ This is a singleton — `create()` returns the same instance every time. It grac
60
60
 
61
61
  ## Getting Langfuse Keys
62
62
 
63
- ### Percepta's Internal Instance
63
+ ### Shared Instances
64
64
 
65
- Percepta runs a shared Langfuse instance. For `percepta-test` deploys, the generated Ryvn installation uses the shared demo project by inheriting `LANGFUSE_PUBLIC_KEY` and sensitive `LANGFUSE_SECRET_KEY` from the `demos-commons` variable group.
66
-
67
- For non-demo environments, verify the target Ryvn environment has a Langfuse installation or shared Langfuse project, then store the project keys in an environment-scoped variable group or installation secrets.
65
+ If the target stack provides a shared Langfuse instance, store
66
+ `LANGFUSE_PUBLIC_KEY` and sensitive `LANGFUSE_SECRET_KEY` through that
67
+ platform's environment-scoped variable or secret mechanism.
68
68
 
69
69
  ### Self-Hosted / Langfuse Cloud
70
70
 
@@ -74,17 +74,17 @@ For external projects, you can:
74
74
 
75
75
  ## Running Locally
76
76
 
77
- ### Option 1: Use Percepta's Langfuse (recommended)
77
+ ### Option 1: Use a Shared Langfuse Instance
78
78
 
79
79
  Set the keys in `.env.local` if you want local traces to go to the shared instance:
80
80
 
81
81
  ```bash
82
- LANGFUSE_BASE_URL=https://langfuse.percepta-test.aitco.dev
82
+ LANGFUSE_BASE_URL=https://langfuse.example.com
83
83
  LANGFUSE_PUBLIC_KEY=pk-lf-...
84
84
  LANGFUSE_SECRET_KEY=sk-lf-...
85
85
  ```
86
86
 
87
- Traces from local dev appear in the shared dashboard under your project.
87
+ Traces from local dev appear in the configured shared dashboard under your project.
88
88
 
89
89
  ### Option 2: Run Langfuse locally
90
90
 
@@ -40,7 +40,9 @@ The shared `@percepta/ai` provider helper chooses a provider at call time:
40
40
 
41
41
  ## Deployment
42
42
 
43
- For `percepta-test`, `deploy:percepta-test` attaches the `demos-commons` Ryvn variable group. That group provides the shared `ANTHROPIC_API_KEY` and Langfuse project keys, so generated demo apps do not need per-app LLM secrets.
43
+ Provider keys and Langfuse credentials should come from the target deployment
44
+ platform. Do not commit shared provider keys or generated environment-specific
45
+ secret files to the app repo.
44
46
 
45
47
  ## Local Development
46
48
 
@@ -54,6 +56,6 @@ ANTHROPIC_API_KEY=sk-ant-...
54
56
 
55
57
  ## Observability
56
58
 
57
- `LLMService` enables AI SDK telemetry by default and attaches provider/model metadata to each call. When `LANGFUSE_*` values are configured, the template's OpenTelemetry bootstrap sends LLM spans to Langfuse. In `percepta-test`, those values are inherited from the environment.
59
+ `LLMService` enables AI SDK telemetry by default and attaches provider/model metadata to each call. When `LANGFUSE_*` values are configured, the template's OpenTelemetry bootstrap sends LLM spans to Langfuse.
58
60
 
59
61
  Use a stable `telemetryFunctionId` for every meaningful LLM operation, such as `extract-invoice-fields` or `draft-member-message`.
@@ -142,8 +142,7 @@ Once all chunks are implemented, verify the app runs end-to-end locally.
142
142
  ### Step 1: Start dependencies
143
143
 
144
144
  ```bash
145
- pnpm docker:up
146
- pnpm db:setup-and-migrate
145
+ pnpm run setup
147
146
  ```
148
147
 
149
148
  If the app uses Inngest functions, start the local Inngest dev server in a separate terminal:
@@ -192,19 +191,21 @@ git init
192
191
  git add -A
193
192
  git commit -m "Initial implementation of <app-name>"
194
193
 
195
- # Create the repo under the Percepta-Core org
196
- gh repo create Percepta-Core/<app-name> --internal --source=. --push
194
+ # Create and push the repo in the target GitHub org
195
+ gh repo create <org>/<app-name> --internal --source=. --push
197
196
  ```
198
197
 
199
198
  If `gh` is not authenticated, tell the user to run `gh auth login` and then continue.
200
199
 
201
200
  ---
202
201
 
203
- ## Phase 6: Deploy to Ryvn (When Requested)
202
+ ## Phase 6: Deploy (When Requested)
204
203
 
205
204
  Only do this when the user explicitly asks to deploy.
206
205
 
207
- Follow the step-by-step guide in [agent-skills/deploy.md](deploy.md). It contains the service definition, installation YAML, environment variables, and secrets needed for percepta-test.
206
+ Deployment is stack-specific. Confirm the target environment and use the
207
+ customer infra repo or deployment guide for that stack. Blueberry does not
208
+ generate environment-specific installation YAML.
208
209
 
209
210
  For Ryvn CLI operations (checking status, logs, troubleshooting), use the `/use-ryvn` skill.
210
211
 
@@ -1,25 +1,21 @@
1
- # Ryvn — Deployment Platform
1
+ # Ryvn
2
2
 
3
- Ryvn is the deployment platform used by Percepta to manage cloud infrastructure. It provisions environments, deploys services, and handles CI/CD abstracting away Kubernetes, Terraform, and cloud provider details.
3
+ Ryvn can be used to register and release this app as a service. Blueberry does
4
+ not generate a target environment installation because those details are
5
+ customer and stack specific.
4
6
 
5
- ## Percepta Environments
7
+ ## Generated Files
6
8
 
7
- | Environment | Purpose | Domain pattern |
8
- |-------------|---------|---------------|
9
- | `percepta-test` | Internal dev/test | `<app>.percepta-test.aitco.dev` |
9
+ - `deploy/ryvn/__APP_NAME__.service.yaml` declares the app service and Docker build context.
10
+ - `.github/workflows/__APP_NAME__-ryvn-release.yaml` builds the image and creates a Ryvn release.
10
11
 
11
- New apps are deployed to **percepta-test** using the existing-environment deploy motion. This environment must already have shared PostgreSQL, Inngest, OTEL collector, LGTM stack, and Langfuse installations before app deploys run. The service installation points at the shared Langfuse URL and attaches the `demos-commons` variable group for shared demo Langfuse project keys.
12
+ ## Environment Installations
12
13
 
13
- ## Deploying This App
14
-
15
- For the full step-by-step deployment guide to percepta-test, see [deploy.md](deploy.md).
14
+ Environment installations belong in the infra repo. A customer blueprint should
15
+ compose the required base infrastructure, monorepo infrastructure, app database
16
+ registration, runtime services, ingress, secrets, and the app service
17
+ installation for the target stack.
16
18
 
17
19
  ## Ryvn CLI
18
20
 
19
21
  For all Ryvn CLI operations (checking status, viewing logs, troubleshooting, managing installations), use the **`/use-ryvn`** skill. It has comprehensive CLI reference docs and handles authentication, deployment, configuration, and operations.
20
-
21
- ```bash
22
- # Quick status check
23
- ryvn get installation __APP_NAME__ -e percepta-test
24
- ryvn logs __APP_NAME__ -e percepta-test
25
- ```
@@ -1,66 +1,25 @@
1
1
  # Deploy
2
2
 
3
- This directory holds Ryvn infrastructure-as-code for deploying __APP_TITLE__ to Percepta environments.
3
+ This directory contains environment-neutral deployment metadata for __APP_TITLE__.
4
+ It intentionally does not include customer or environment installation files.
4
5
 
5
6
  ```
6
7
  deploy/
7
8
  └── ryvn/
8
- ├── __APP_NAME__.service.yaml
9
- ├── __APP_NAME__-terraform.service.yaml
10
- └── environments/
11
- └── percepta-test/
12
- └── installations/
13
- ├── __APP_NAME__.env.percepta-test.serviceinstallation.yaml
14
- └── __APP_NAME__-terraform.env.percepta-test.serviceinstallation.yaml
9
+ └── __APP_NAME__.service.yaml
15
10
  ```
16
11
 
17
- These files deploy to `https://__APP_NAME__.percepta-test.aitco.dev`.
18
-
19
- The default deploy helper performs the existing-environment deploy motion: it assumes the target Ryvn environment already has the shared platform services installed, then wires this app into them. For `percepta-test`, that means shared Postgres, Inngest, the OTEL collector, the LGTM stack, and Langfuse must already exist before app deploy starts. Fresh-environment platform bootstrap is a separate motion and should be handled by a Ryvn blueprint or environment-specific platform rollout.
20
-
21
- The `pnpm deploy:percepta-test` script delegates to the versioned `@percepta/deploy` CLI. The app owns only the Ryvn service/installation YAML and secrets env file. The helper talks directly to Ryvn: it preflights the existing platform services, creates/updates the services, runs the GitHub Actions release workflows, creates the schema installation, approves the schema Terraform plan, creates or updates app-scoped Ryvn secrets, creates the web installation, waits for health, and verifies the health and app routes.
22
-
23
- ## Deploying
24
-
25
- Tell Claude "deploy this app to percepta-test" or run:
26
-
27
- ```bash
28
- pnpm deploy:percepta-test -- --yes
29
- ```
30
-
31
- The helper expects a clean, committed git worktree because GitHub Actions builds from the pushed repo. It can create `Percepta-Core/__REPO_NAME__` if it does not exist yet, and it pushes the current branch to `main` before triggering releases.
12
+ The generated app owns its buildable service identity. The infra repo owns
13
+ customer blueprints, environment installations, app database registration,
14
+ runtime dependencies, ingress, secrets, and rollout policy.
32
15
 
33
16
  ## What's in these files
34
17
 
35
18
  **`__APP_NAME__.service.yaml`** — Ryvn server service for the web app. It points at `Percepta-Core/__REPO_NAME__` and builds from `packages/__APP_NAME__/`.
36
19
 
37
- **`__APP_NAME__-terraform.service.yaml`** — Ryvn Terraform service that owns the per-app Postgres schema in the shared `demos` database.
38
-
39
- **`__APP_NAME__.env.percepta-test.serviceinstallation.yaml`** — web app installation for `percepta-test`. It wires the shared platform services, ingress, health probes, database connection, Inngest, OTEL/LGTM telemetry, the Langfuse base URL, and the shared demo variable group.
40
-
41
- **`__APP_NAME__-terraform.env.percepta-test.serviceinstallation.yaml`** — schema installation for `percepta-test`.
42
-
43
- **`percepta-test.secrets.env`** — generated locally and ignored by git. The deploy helper injects app-specific auth/encryption secrets into the Ryvn installation create manifest so the first pod starts with auth configured; shared Langfuse and LLM demo keys are inherited from a Ryvn variable group.
44
-
45
- ## Platform Wiring
46
-
47
- `pnpm deploy:percepta-test` checks these existing `percepta-test` installations before it mutates GitHub or Ryvn app resources:
48
-
49
- - `percepta-internal-terraform` for the shared Postgres instance.
50
- - `inngest-test` for background jobs and function callbacks.
51
- - `otel-collector` for trace, metric, and log collection.
52
- - `lgtm-stack-helm` for Loki, Grafana, Tempo, and Mimir.
53
- - `langfuse` for LLM tracing and eval observability.
54
- - `demos-commons` variable group for shared demo configuration, including the Anthropic API key and Langfuse demo project keys.
55
-
56
- The service installation sets `LANGFUSE_BASE_URL` to the shared `percepta-test` Langfuse URL, sets `LLM_PROVIDER=anthropic`, and attaches `demos-commons` for `ANTHROPIC_API_KEY`, `LANGFUSE_PUBLIC_KEY`, and sensitive `LANGFUSE_SECRET_KEY`. Individual demo apps do not need LLM or Langfuse keys in `percepta-test.secrets.env`.
57
-
58
20
  ## Notes
59
21
 
60
- The release workflows live at the repo root under `.github/workflows/`. The web workflow uses the org-level `NPM_TOKEN` secret for private `@percepta/*` packages; do not add a repo-level token unless the org secret is unavailable.
61
-
62
- For the old GitOps PR path, use `pnpm deploy:percepta-test:pr -- --phase service --yes` and then `pnpm deploy:percepta-test:pr -- --phase installation --yes`.
63
-
64
- ## Adding More Environments
65
-
66
- Copy the two `percepta-test` installation manifests to `environments/<env>/installations/`, then change the `environment:`, host, and environment-specific config.
22
+ The release workflow lives at the repo root under `.github/workflows/` after
23
+ scaffolding. It creates a Ryvn service release from the current app image.
24
+ Installing that release into any environment is a customer/stack-specific
25
+ infra concern and should be modeled in the infra repo.
@@ -1,5 +1,4 @@
1
1
  import * as nextEnvModule from "@next/env";
2
- import { getPgSearchPathOption } from "@percepta/database";
3
2
  import type { Config } from "drizzle-kit";
4
3
  import { getEnvConfig } from "./src/config/getEnvConfig";
5
4
 
@@ -9,34 +8,14 @@ const nextEnv =
9
8
 
10
9
  nextEnv.loadEnvConfig(process.cwd());
11
10
 
12
- const {
13
- DATABASE_HOST: host,
14
- DATABASE_PORT: port,
15
- DATABASE_USERNAME: user,
16
- DATABASE_PASSWORD: password,
17
- DATABASE_NAME: database,
18
- DATABASE_SCHEMA: databaseSchema,
19
- DATABASE_USE_SSL: useSSL,
20
- } = getEnvConfig();
21
-
22
- const schemaFilter = databaseSchema?.trim() || undefined;
23
- const searchPathOption = getPgSearchPathOption(schemaFilter);
24
- const connectionParams = new URLSearchParams();
25
- if (useSSL) connectionParams.set("sslmode", "require");
26
- if (searchPathOption) connectionParams.set("options", searchPathOption);
27
-
28
- const connectionString =
29
- `postgresql://${encodeURIComponent(user)}:${encodeURIComponent(password)}` +
30
- `@${host}:${port}/${encodeURIComponent(database)}` +
31
- (connectionParams.size > 0 ? `?${connectionParams.toString()}` : "");
11
+ const { DATABASE_URL: databaseUrl } = getEnvConfig();
32
12
 
33
13
  const config: Config = {
34
14
  schema: "./src/drizzle/schema",
35
15
  out: "./src/drizzle/migrations",
36
16
  dialect: "postgresql",
37
- ...(schemaFilter ? { schemaFilter: [schemaFilter] } : {}),
38
17
  dbCredentials: {
39
- url: connectionString,
18
+ url: databaseUrl,
40
19
  },
41
20
  };
42
21
 
@@ -2,21 +2,16 @@
2
2
  NODE_ENV=development
3
3
  APP_BASE_URL=http://localhost:3000
4
4
 
5
- # Database
6
- DATABASE_HOST=localhost
7
- DATABASE_PORT=5434
8
- DATABASE_USERNAME=postgres
9
- DATABASE_PASSWORD=postgres
10
- DATABASE_NAME=__DB_NAME__
11
- # DATABASE_SCHEMA=
12
- DATABASE_USE_SSL=false
5
+ # App Database
6
+ DATABASE_URL=postgresql://postgres:postgres@localhost:5434/__DB_NAME__
13
7
 
14
8
  # Authentication (Better Auth)
15
9
  BETTER_AUTH_SECRET=generate-with-openssl-rand-base64-32
16
10
  BETTER_AUTH_URL=http://localhost:3000
17
- # Optional override for the shared customer auth database. Defaults to the
18
- # customer monorepo database generated in ../../auth.
19
- # AUTH_DATABASE_NAME=
11
+
12
+ # Shared Auth Database
13
+ # Deployed apps should set this from the customer monorepo auth database Secret.
14
+ # Local development can leave it empty and use the shared auth package defaults.
20
15
  # AUTH_DATABASE_URL=
21
16
 
22
17
  # Security
@@ -46,9 +41,8 @@ NEXT_PUBLIC_FARO_APP_ENVIRONMENT=development
46
41
  # LANGFUSE_SECRET_KEY=
47
42
 
48
43
  # LLM providers
49
- # Deployed percepta-test apps inherit ANTHROPIC_API_KEY from the demos-commons
50
- # Ryvn variable group. For local LLM testing, set ANTHROPIC_API_KEY once in your
51
- # shell profile or ~/.config/percepta/create.env.
44
+ # For local LLM testing, set ANTHROPIC_API_KEY once in your shell profile or
45
+ # ~/.config/percepta/create.env.
52
46
  # ANTHROPIC_API_KEY=
53
47
  # OPENAI_API_KEY=
54
48
  # LLM_PROVIDER=anthropic
@@ -11,21 +11,15 @@
11
11
  "start": "next start",
12
12
  "lint": "eslint .",
13
13
  "setup": "pnpm --dir ../.. run setup",
14
- "docker:up": "docker compose up -d --wait",
15
- "docker:down": "docker compose down",
16
14
  "access:validate": "percepta-access-control validate",
17
15
  "access:apply-local": "pnpm --dir ../.. run access:apply-local",
18
- "auth:db:setup-and-migrate": "pnpm --dir ../.. run auth:db:setup-and-migrate",
16
+ "auth:db:migrate": "pnpm --dir ../.. run auth:db:migrate",
19
17
  "inngest:dev": "pnpm dlx inngest-cli@latest dev -u http://localhost:3000/api/inngest",
20
18
  "db:generate": "percepta-db generate-migrations",
21
- "db:migrate": "percepta-db migrate --database __DB_NAME__",
22
- "db:setup": "percepta-db setup --database __DB_NAME__",
23
- "db:setup-and-migrate": "pnpm db:setup && pnpm db:migrate",
24
- "db:setup-readonly": "percepta-db setup-readonly --database __DB_NAME__",
25
- "db:studio": "pnpm db:setup-and-migrate && drizzle-kit studio",
19
+ "db:migrate": "percepta-db migrate",
20
+ "db:setup-readonly": "percepta-db setup-readonly",
21
+ "db:studio": "pnpm db:migrate && drizzle-kit studio",
26
22
  "db:seed": "tsx ./scripts/seed.ts",
27
- "deploy:percepta-test": "percepta-deploy percepta-test --app __APP_NAME__ --repo __REPO_NAME__",
28
- "deploy:percepta-test:pr": "percepta-deploy percepta-test pr --app __APP_NAME__ --database-schema __APP_NAME_SNAKE__",
29
23
  "test": "vitest run",
30
24
  "test:e2e": "pnpm run setup && playwright test",
31
25
  "test:e2e:install": "playwright install chromium",
@@ -54,7 +48,7 @@
54
48
  "@__REPO_NAME__/auth": "workspace:*",
55
49
  "@percepta/access-control": "0.8.0",
56
50
  "@percepta/ai": "0.1.0",
57
- "@percepta/database": "0.1.1",
51
+ "@percepta/database": "0.1.2",
58
52
  "@percepta/design": "0.4.0",
59
53
  "@percepta/inngest": "0.1.0",
60
54
  "@percepta/logger": "0.1.0",
@@ -102,7 +96,6 @@
102
96
  "@next/eslint-plugin-next": "^15.3.5",
103
97
  "@playwright/test": "^1.58.2",
104
98
  "@percepta/build": "0.4.0",
105
- "@percepta/deploy": "0.1.0",
106
99
  "@tailwindcss/postcss": "^4.1.11",
107
100
  "@types/formidable": "^3.4.5",
108
101
  "@types/he": "^1.2.3",
@@ -1,24 +1,20 @@
1
- # Check if database connection variables are set
2
- if [ -z "$DATABASE_HOST" ] || [ -z "$DATABASE_USERNAME" ] || [ -z "$DATABASE_NAME" ]; then
3
- echo "⚠️ Database connection not configured. Skipping migration."
4
- echo "Required environment variables: DATABASE_HOST, DATABASE_USERNAME, DATABASE_NAME"
5
- echo "❌ Error: Missing required database environment variables."
1
+ # Check if app database connection variables are set
2
+ if [ -z "$DATABASE_URL" ]; then
3
+ echo "⚠️ App database connection not configured. Skipping migration."
4
+ echo "Required environment variable: DATABASE_URL"
5
+ echo "❌ Error: Missing required app database environment variables."
6
6
  exit 1
7
7
  else
8
- echo "Database configuration found:"
9
- echo " HOST: $DATABASE_HOST"
10
- echo " USER: $DATABASE_USERNAME"
11
- echo " DATABASE: $DATABASE_NAME"
12
- echo " SSL: ${DATABASE_USE_SSL:-false}"
8
+ echo "App database configuration found."
13
9
  fi
14
10
 
15
- # Run database migrations only if database is configured
16
- echo "Running database migrations..."
17
- if pnpm db:setup-and-migrate; then
18
- echo "✅ Database migrations completed successfully"
11
+ # Run app database migrations only if database is configured
12
+ echo "Running app database migrations..."
13
+ if pnpm db:migrate; then
14
+ echo "✅ App database migrations completed successfully"
19
15
  else
20
- echo "❌ Database migration failed. App will not start."
21
- echo "Check your database configuration and connectivity."
16
+ echo "❌ App database migration failed. App will not start."
17
+ echo "Check your app database configuration and connectivity."
22
18
  exit 1
23
19
  fi
24
20
 
@@ -10,17 +10,10 @@ export const { getEnvConfig, schema: ENV_CONFIG_SCHEMA } = createEnvConfig(
10
10
  // Application:
11
11
  APP_BASE_URL: z.string().optional(),
12
12
 
13
- // Database:
14
- DATABASE_HOST: z.string().default("localhost"),
15
- DATABASE_PORT: z.coerce.number().int().default(5434),
16
- DATABASE_USERNAME: z.string().default("postgres"),
17
- DATABASE_PASSWORD: z.string().default("postgres"),
18
- DATABASE_NAME: z.string().default("__DB_NAME__"),
19
- DATABASE_SCHEMA: z.string().optional(),
20
- DATABASE_USE_SSL: z
13
+ // App database:
14
+ DATABASE_URL: z
21
15
  .string()
22
- .transform((value: string): boolean => value === "true")
23
- .default(false),
16
+ .default("postgresql://postgres:postgres@localhost:5434/__DB_NAME__"),
24
17
 
25
18
  // AWS:
26
19
  AWS_REGION: z.string().default("us-east-1"),
@@ -28,6 +21,7 @@ export const { getEnvConfig, schema: ENV_CONFIG_SCHEMA } = createEnvConfig(
28
21
  // Authentication (Better Auth):
29
22
  BETTER_AUTH_SECRET: z.string().optional(),
30
23
  BETTER_AUTH_URL: z.string().default("http://localhost:3000"),
24
+ AUTH_DATABASE_URL: z.string().optional(),
31
25
 
32
26
  // Inngest:
33
27
  INNGEST_BASE_URL: z.string().optional(),
@@ -1,30 +1,15 @@
1
- import { getPgSearchPathOption, getPgSslConfig } from "@percepta/database";
1
+ import { createPgPool, readDatabaseConfig } from "@percepta/database";
2
2
  import { type NodePgDatabase, drizzle } from "drizzle-orm/node-postgres";
3
- import { Pool } from "pg";
3
+ import type { Pool } from "pg";
4
4
  import { getEnvConfig } from "../config/getEnvConfig";
5
5
 
6
6
  export const { client, db } = createDb();
7
7
 
8
8
  function createDb(): { client: Pool; db: NodePgDatabase } {
9
- const {
10
- DATABASE_HOST: host,
11
- DATABASE_PORT: port,
12
- DATABASE_USERNAME: user,
13
- DATABASE_PASSWORD: password,
14
- DATABASE_NAME: database,
15
- DATABASE_SCHEMA: databaseSchema,
16
- DATABASE_USE_SSL: useSSL,
17
- } = getEnvConfig();
18
-
19
- const pool = new Pool({
20
- host,
21
- port,
22
- user,
23
- password,
24
- database,
25
- ssl: getPgSslConfig(useSSL),
26
- options: getPgSearchPathOption(databaseSchema),
27
- });
9
+ const { DATABASE_URL: databaseUrl } = getEnvConfig();
10
+ const pool = createPgPool(
11
+ readDatabaseConfig({ env: { DATABASE_URL: databaseUrl } }),
12
+ );
28
13
 
29
14
  return { client: pool, db: drizzle(pool) };
30
15
  }
@@ -1,9 +1,14 @@
1
+ import { client as authClient } from "@__REPO_NAME__/auth/db";
1
2
  import { getEnvConfig } from "./config/getEnvConfig";
2
3
  import { client } from "./drizzle/db";
3
4
  import { getLogger } from "./services/logger/AppLogger";
4
5
 
5
6
  export async function checkStartup(): Promise<boolean> {
6
- return validateEnvironment() && (await validateDatabaseConnection());
7
+ return (
8
+ validateEnvironment() &&
9
+ (await validateDatabaseConnection()) &&
10
+ (await validateAuthDatabaseConnection())
11
+ );
7
12
  }
8
13
 
9
14
  function validateEnvironment(): boolean {
@@ -18,15 +23,31 @@ function validateEnvironment(): boolean {
18
23
 
19
24
  async function validateDatabaseConnection(): Promise<boolean> {
20
25
  try {
21
- const dbCheckPromise = client.query("SELECT 1");
22
-
23
- const timeoutPromise = new Promise((_, reject) =>
24
- setTimeout(() => reject(new Error("Database check timeout")), 5000),
25
- );
26
- await Promise.race([dbCheckPromise, timeoutPromise]);
26
+ await checkDatabaseClient(client, "Database check timeout");
27
27
  } catch {
28
28
  getLogger().warn(undefined, "Database connection failed");
29
29
  return false;
30
30
  }
31
31
  return true;
32
32
  }
33
+
34
+ async function validateAuthDatabaseConnection(): Promise<boolean> {
35
+ try {
36
+ await checkDatabaseClient(authClient, "Auth database check timeout");
37
+ } catch {
38
+ getLogger().warn(undefined, "Auth database connection failed");
39
+ return false;
40
+ }
41
+ return true;
42
+ }
43
+
44
+ async function checkDatabaseClient(
45
+ databaseClient: Pick<typeof client, "query">,
46
+ timeoutMessage: string,
47
+ ): Promise<void> {
48
+ const dbCheckPromise = databaseClient.query("SELECT 1");
49
+ const timeoutPromise = new Promise((_, reject) =>
50
+ setTimeout(() => reject(new Error(timeoutMessage)), 5000),
51
+ );
52
+ await Promise.race([dbCheckPromise, timeoutPromise]);
53
+ }
@@ -1,11 +0,0 @@
1
- import { setupAuthDatabase } from "@percepta/auth";
2
- import { getAuthDatabaseConfig } from "../src/config/database";
3
-
4
- async function main(): Promise<void> {
5
- await setupAuthDatabase({ config: getAuthDatabaseConfig() });
6
- }
7
-
8
- void main().catch((error) => {
9
- console.error("Shared auth database setup failed:", error);
10
- process.exit(1);
11
- });