Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/preview-api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -342,12 +342,12 @@ jobs:
'',
'#### Database',
'',
'- **Mode:** SQLite (ephemeral) — an isolated, disposable database baked into this image; never the shared Azure SQL database.',
'- **Mode:** SQLite (ephemeral) — an isolated, disposable database baked into this image; never the shared PostgreSQL database.',
`- **Active scenarios:** ${scenarios.map((s) => `\`${s}\``).join(', ')}`,
'- **Reset behaviour:** every container start (including a redeploy after pushing new commits) copies the immutable seeded template back over the writable database — any changes made while testing are discarded, not carried forward.',
'- **Verify without manual setup:** `GET /health/db` returns `200` only once every active scenario\'s fixtures were found in this container\'s copy of the database (see `docker-entrypoint.sh`).',
'',
'See [`docs/preview-scenarios.md`](https://github.com/singleton-sd/poc-plattform-kit/blob/main/docs/preview-scenarios.md) for each scenario\'s test instructions and known SQLite vs SQL Server limitations.',
'See [`docs/preview-scenarios.md`](https://github.com/singleton-sd/poc-plattform-kit/blob/main/docs/preview-scenarios.md) for each scenario\'s test instructions and known SQLite vs PostgreSQL limitations.',
'',
'Web SWA PR previews remain via `preview-web.yml`; production API/web via `deploy-api.yml` / `deploy-web.yml` on `main`.',
].join('\n');
Expand Down
2 changes: 1 addition & 1 deletion SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ Copy the JSON config to onboard another domain later (see `docs/dns-route53.md`)

| Kind | Name | URL / notes | SKU |
| --- | --- | --- | --- |
| Neon PostgreSQL (PoC; IaC no longer provisions Azure SQL — see [#291](https://github.com/singleton-sd/poc-plattform-kit/issues/291) / [#298](https://github.com/singleton-sd/poc-plattform-kit/pull/298); live server delete is [#292](https://github.com/singleton-sd/poc-plattform-kit/issues/292)) | project `round-union-05852948` / `neondb` | Key Vault `database-url` (+ `database-url-unpooled`) | Neon |
| Neon PostgreSQL (PoC) | project `round-union-05852948` / `neondb` | Key Vault `database-url` (+ `database-url-unpooled`); Azure SQL removed ([#292](https://github.com/singleton-sd/poc-plattform-kit/issues/292)) | Neon |
| App Service Plan + API | `pocpk-plan` / `pocpk-api-si5fhs6dvxiha` | https://api.plattform-kit.poc.singletonsd.com (default: `....azurewebsites.net`) | **B1** |
| Static Web App (app) | `pocpk-web-si5fhs6dvxiha` | https://app.plattform-kit.poc.singletonsd.com (default: `....azurestaticapps.net`) | Free |
| Static Web App (marketing) | `ssd-pocpk-mkt-dev-ae` | https://plattform-kit.poc.singletonsd.com (PR previews need `stagingEnvironmentPolicy=Enabled`) | Free |
Expand Down
12 changes: 6 additions & 6 deletions apps/api/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
# --build-arg PREVIEW_SEED_SCENARIOS=demo .
#
# Production/App Service deploys use scripts/stage-api-deploy.sh (zip
# deploy), never this Dockerfile, and always generate the canonical SQL
# Server Prisma client from prisma/schema.prisma unchanged.
# deploy), never this Dockerfile, and always generate the canonical
# PostgreSQL Prisma client from prisma/schema.prisma unchanged.
#
# This image instead derives a SQLite-compatible preview schema at build
# time (scripts/generate-preview-schema.mjs), generates a SQLite Prisma
Expand All @@ -15,7 +15,7 @@
# into the image. docker-entrypoint.sh copies that template to a writable
# runtime path on every container start, so a preview always resets to the
# same deterministic seeded state and never resolves or mutates the shared
# Azure SQL database — see AGENTS.md and docs/preview-scenarios.md.
# PostgreSQL database — see AGENTS.md and docs/preview-scenarios.md.
#
# Runtime packaging otherwise mirrors scripts/stage-api-deploy.sh:
# - hoisted pnpm deploy --prod
Expand All @@ -42,7 +42,7 @@ RUN pnpm --filter @poc-plattform-kit/api build
# scenarios declared by the PR; "demo" is the default baseline.
ARG PREVIEW_SEED_SCENARIOS=demo

# Derive the SQLite preview schema from the canonical SQL Server schema.
# Derive the SQLite preview schema from the canonical PostgreSQL schema.
# Fails the build with an actionable diagnostic (not a silently broken
# preview) when the canonical schema uses a construct the SQLite connector
# can't represent.
Expand All @@ -51,8 +51,8 @@ RUN node /app/packages/db/scripts/generate-preview-schema.mjs \
/app/packages/db/prisma/schema.preview.prisma

# Match App Service staging shape (hoisted deploy tree), but generate a
# SQLite client + an immutable SQLite database template instead of the SQL
# Server client production deploys use.
# SQLite client + an immutable SQLite database template instead of the
# production PostgreSQL client.
# Resolve prisma via node (pnpm .bin shims can vanish after re-linking for deploy).
RUN PRISMA_JS="$(find /app/node_modules -path '*/node_modules/prisma/build/index.js' | head -n 1)" \
&& test -n "$PRISMA_JS" \
Expand Down
2 changes: 1 addition & 1 deletion apps/api/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ cp "$TEMPLATE_DB" "$RUNTIME_DB"
chmod 0644 "$RUNTIME_DB"

# Explicit and set before Nest (and app-configuration.ts) start, so the
# shared Azure SQL App Configuration value is never resolved for previews —
# shared PostgreSQL App Configuration value is never resolved for previews —
# see apps/api/src/config/app-configuration.ts (explicit env vars win).
export DATABASE_URL="file:${RUNTIME_DB}"

Expand Down
2 changes: 1 addition & 1 deletion apps/marketing/src/content/pages/privacy.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ We use providers that may process data to operate the Service:
| Service | Purpose | Data shared |
| --- | --- | --- |
| Microsoft Entra ID | Authentication | Identity claims, session data |
| Azure SQL | Application data storage | Service records |
| Neon PostgreSQL | Application data storage | Service records |
| Azure App Configuration / Key Vault | Configuration and secrets | App settings (secrets in Key Vault) |
| Azure Service Bus | Events and jobs | Message payloads for domain events |
| Azure Application Insights | Traces, exceptions, performance diagnostics | Request/telemetry events, browser diagnostics, errors |
Expand Down
2 changes: 1 addition & 1 deletion docs/discovery/support-impersonation.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ The context is immutable after guards/interceptors establish it. Domain services

### Assets and trust boundaries

Assets are tenant data, customer identity, support grants, active-ticket evidence, session credentials, audit history, and customer trust. Trust boundaries exist between browser and API, Entra and API, API and OpenFGA, API and Azure SQL, Support and other pillars, and runtime telemetry/exporters.
Assets are tenant data, customer identity, support grants, active-ticket evidence, session credentials, audit history, and customer trust. Trust boundaries exist between browser and API, Entra and API, API and OpenFGA, API and PostgreSQL, Support and other pillars, and runtime telemetry/exporters.

| Threat | Example attack | Required control / verification |
| --- | --- | --- |
Expand Down
31 changes: 31 additions & 0 deletions docs/neon-cutover-292.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Neon cutover run record (#292)

Completed 2026-09-09 against subscription `ssd-poc-plattform-kit` / RG `rg-poc-plattform-kit`.

## Cutover

1. **Neon CLI** (`pnpm exec neon connection-string`) for project `round-union-05852948` / branch `production` / database `neondb`:
- Pooled URL → Key Vault `database-url`
- Direct URL → Key Vault `database-url-unpooled`
2. Prior Azure SQL `database-url` value saved as **historical backup data** in Key Vault `database-url-rollback-azure-sql`. It is **not** an executable rollback path — the Azure SQL database and server were deleted in the same cutover. Recovery would require provisioning a new Postgres (or Azure SQL) target, restoring from an independent backup if one exists, updating Key Vault `database-url*`, and redeploying the API.
3. `./infra/migrate-db.sh` — schema already up to date (`20260828110000_init_postgresql`).
4. Seeded `pillar/tenant/owner` + `pillar/tenant/settings` via `packages/db/scripts/seed.mjs` against Neon (`@prisma/client`).
5. **Production API redeploy**: last App Service deploy before cutover was 2026-08-22 (pre-`postgresql` Prisma). Manual `workflow_dispatch` of **Deploy API (App Service)** on `main` after KV switch — run [34352978088](https://github.com/singleton-sd/poc-plattform-kit/actions/runs/34352978088) succeeded.

## Decommission

- Deleted Azure SQL database `pocpk` and server `pocpk-sql-si5fhs6dvxiha`.
- Soft-deleted + purged Key Vault `sql-admin-password`.
- Removed App Configuration key `secret:sql-admin-password`.
- `az sql server list` on the RG returns empty.

## Verification

- `GET /health` → 200 after redeploy.
- `GET /health/db` → 200 after redeploy (500 while App Service still ran the Aug SQL Server build against a Postgres URL).
- App Service `DATABASE_URL` remains `@Microsoft.KeyVault(.../secrets/database-url/)` (unversioned).

## Follow-ups

- Purge `database-url-rollback-azure-sql` after a short observation window (audit artifact only).
- Close epic #288 once human confirms billing / App Insights look healthy.
4 changes: 2 additions & 2 deletions infra/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Example: `ssd-pocpk-kv-dev-ae`, `ssd-pocpk-appcs-dev-ae`
| env | `dev` |
| region | `ae` = australiaeast; SWA Free may stay `eastasia` |

**Existing resources (legacy — do not rename):** `pocpk-{resource}-{uniqueString}` from first deploy. Renaming would recreate API/SWA/SB. Keep them; map in docs. Legacy Azure SQL (`pocpk-sql-…`) is no longer in `main.bicep`; delete after Neon cutover (#292).
**Existing resources (legacy — do not rename):** `pocpk-{resource}-{uniqueString}` from first deploy. Renaming would recreate API/SWA/SB. Keep them; map in docs. Legacy Azure SQL (`pocpk-sql-…`) was deleted in [#292](https://github.com/singleton-sd/poc-plattform-kit/issues/292) after Neon cutover.

## Resources (live)

Expand Down Expand Up @@ -237,7 +237,7 @@ az keyvault secret set --vault-name ssd-pocpk-kv-dev-ae --name database-url-unpo

`deploy.sh` only upserts local `DATABASE_URL*` when the scheme is `postgresql://` / `postgres://` (rejects leftover `sqlserver://` values from older deploys). `migrate-db.sh` fails closed if `database-url-unpooled` is missing.

App Service continues to resolve `DATABASE_URL` from `@Microsoft.KeyVault(.../secrets/database-url/)`. Do not recreate `sql-admin-password` — Azure SQL is out of IaC; live server deletion is #292.
App Service continues to resolve `DATABASE_URL` from `@Microsoft.KeyVault(.../secrets/database-url/)`. Azure SQL server/DB and `sql-admin-password` were removed in the [#292](https://github.com/singleton-sd/poc-plattform-kit/issues/292) cutover (see [`docs/neon-cutover-292.md`](../docs/neon-cutover-292.md)).

```bash
./infra/migrate-db.sh --what-if
Expand Down
2 changes: 1 addition & 1 deletion infra/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,6 @@ Next steps:
6. Wire App Service / SWA / ACA to App Configuration provider + managed identity
7. ./infra/migrate-db.sh against Neon (Prisma postgresql)
8. Never store deploy tokens or connection strings in GitHub Secrets
9. After cutover validation, delete legacy Azure SQL (#292)
9. Neon cutover + Azure SQL decommission recorded in docs/neon-cutover-292.md (#292)

EOF
Loading