OPC # 0001: Extract OPC into standalone repo

This commit is contained in:
amadzarak
2026-04-25 17:26:42 -04:00
commit 42383bdc03
170 changed files with 21365 additions and 0 deletions
+108
View File
@@ -0,0 +1,108 @@
-- =============================================================================
-- OPC Seed Script seeded from TODO.md backlog
-- Run against the ControlPlane database.
-- OPC # 0001 is already live; this starts at 0002.
-- =============================================================================
INSERT INTO opc (id, number, title, description, type, status, priority, assignee, created_at, updated_at)
VALUES
-- ── Keycloak / Auth ───────────────────────────────────────────────────────────
(
gen_random_uuid(),
'OPC # 0002',
'Fix KeycloakStep 401 on realm provisioning',
'KeycloakStep is the current blocker in the provisioning saga. The step returns 401 when attempting to create the tenant realm. Investigate the admin-client credentials, token scope, and the endpoint URL used inside the Docker network.',
'Bug',
'In Progress',
'High',
'amadzarak',
NOW(), NOW()
),
(
gen_random_uuid(),
'OPC # 0003',
'KeycloakStep: full realm + user provisioning flow',
'After the 401 is resolved, implement the full flow: create realm {subdomain}.clarity.io, create the admin role, create the day-zero admin user from AdminEmail, assign the admin role, and trigger execute-actions-email (verify email + set password).',
'Feature',
'New',
'High',
'amadzarak',
NOW(), NOW()
),
(
gen_random_uuid(),
'OPC # 0004',
'Keycloak JWT backchannel issuer cleanup',
'Keycloak advertises its issuer based on the incoming request URL. When the backchannel hits http://keycloak:8080 directly it returns http://keycloak.clarity.test:8080 as the issuer, forcing layered workarounds in ValidIssuers and the rewrite handler. Clean fix: boot Keycloak with KC_HOSTNAME_URL=https://keycloak.clarity.test, verify via /.well-known/openid-configuration, then simplify ValidIssuers back to two entries. Deferred until next planned maintenance window (requires nuke to apply env var).',
'Tech Debt',
'New',
'Medium',
'amadzarak',
NOW(), NOW()
),
-- ── VaultStep ─────────────────────────────────────────────────────────────────
(
gen_random_uuid(),
'OPC # 0005',
'VaultStep: read root token and write initial secrets',
'Read the root token from /vault/file/init.json, enable KV-v2 secrets engine at {subdomain}/, then write the initial secrets: DB connection string and Keycloak client secret.',
'Feature',
'New',
'High',
'amadzarak',
NOW(), NOW()
),
-- ── MigrationStep ─────────────────────────────────────────────────────────────
(
gen_random_uuid(),
'OPC # 0006',
'MigrationStep: run EF Core migrations per provisioning mode',
'Wire up EF Core migrations inside MigrationStep for all three provisioning modes. Shared: run against the shared DB scoped to the tenant schema. Isolated: run against the dedicated Postgres container registered in SagaContext. Dedicated: run against the full dedicated Postgres instance.',
'Feature',
'New',
'Medium',
'amadzarak',
NOW(), NOW()
),
-- ── HandoffStep ───────────────────────────────────────────────────────────────
(
gen_random_uuid(),
'OPC # 0007',
'HandoffStep: send magic-link email and mark saga complete',
'Send a magic-link / welcome email to AdminEmail via SMTP or SendGrid, then mark CompletedSteps.HandoffSent on the provisioning job. Blocked until SMTP is wired (currently SendRequiredActionsEmailAsync is commented out in KeycloakStep.cs).',
'Feature',
'New',
'Medium',
'amadzarak',
NOW(), NOW()
),
-- ── Observability ─────────────────────────────────────────────────────────────
(
gen_random_uuid(),
'OPC # 0008',
'Stream tenant container logs into Aspire dashboard',
'Use the Docker SDK to tail fdev-app-clarity-* container logs and forward them to Aspire''s structured log stream. Currently these logs are only visible via docker logs on the host.',
'Feature',
'New',
'Low',
'amadzarak',
NOW(), NOW()
),
-- ── Kubernetes (backburner) ───────────────────────────────────────────────────
(
gen_random_uuid(),
'OPC # 0009',
'Kubernetes migration path evaluation',
'Currently managing containers directly via Docker.DotNet. Evaluate k8s when: scheduling across multiple nodes is needed, rolling deploys are required, or client count exceeds single-host capacity. Options: k3s (self-hosted), AKS/EKS (cloud), or keep Docker Compose per host for mid-scale. ClarityContainerService abstraction is intentional swap Docker.DotNet for a k8s client without changing the saga.',
'General',
'New',
'Low',
'amadzarak',
NOW(), NOW()
);
+119
View File
@@ -0,0 +1,119 @@
-- =============================================================================
-- OPC Seed Script 2 completed work from TODO.md
-- Run against the ControlPlane database.
-- Picks up numbering at 0010 (00010009 covered in seed_opc.sql).
-- =============================================================================
INSERT INTO opc (id, number, title, description, type, status, priority, assignee, created_at, updated_at)
VALUES
(
gen_random_uuid(),
'OPC # 0010',
'Aspire AppHost wired: Vault, MinIO, RabbitMQ, Postgres, Keycloak, Worker, API, UI',
'Full Aspire AppHost configuration completed. All infrastructure services (Vault, MinIO, RabbitMQ, Postgres, Keycloak) and application services (Worker, API, UI) are registered and wired in the AppHost project.',
'Feature',
'Done',
'High',
'amadzarak',
NOW(), NOW()
),
(
gen_random_uuid(),
'OPC # 0011',
'Fix CRLF → LF on entrypoint.sh (was breaking Vault container)',
'entrypoint.sh had Windows-style CRLF line endings which caused the Vault container to fail on startup. Fixed by enforcing LF via .gitattributes.',
'Bug',
'Done',
'High',
'amadzarak',
NOW(), NOW()
),
(
gen_random_uuid(),
'OPC # 0012',
'Vault initialises and unseals on first run',
'Vault container now correctly initialises (generates root token + unseal keys) and auto-unseals on first run. Init output is written to /vault/file/init.json.',
'Feature',
'Done',
'High',
'amadzarak',
NOW(), NOW()
),
(
gen_random_uuid(),
'OPC # 0013',
'Pin Keycloak bootstrap password (fix persistent container password drift)',
'Keycloak was experiencing password drift between container restarts due to the bootstrap admin credentials not being pinned. Fixed by explicitly setting the admin password so it persists across restarts.',
'Bug',
'Done',
'High',
'amadzarak',
NOW(), NOW()
),
(
gen_random_uuid(),
'OPC # 0014',
'Fix Keycloak endpoint name: tcp → http',
'Keycloak Aspire resource was registered with a tcp endpoint name instead of http, causing service discovery failures. Renamed to http to align with the rest of the stack.',
'Bug',
'Done',
'Medium',
'amadzarak',
NOW(), NOW()
),
(
gen_random_uuid(),
'OPC # 0015',
'Worker starts and correctly waits for all dependencies',
'The Worker service was starting before infrastructure dependencies were healthy. Implemented proper wait/health-check logic so the Worker blocks until Postgres, Keycloak, Vault, RabbitMQ, and MinIO are all ready.',
'Bug',
'Done',
'High',
'amadzarak',
NOW(), NOW()
),
(
gen_random_uuid(),
'OPC # 0016',
'MassTransit saga pipeline with compensation',
'Implemented the full MassTransit-based provisioning saga with forward steps and compensating transactions. Each step registers its rollback so a mid-saga failure cleanly tears down any already-provisioned resources.',
'Feature',
'Done',
'High',
'amadzarak',
NOW(), NOW()
),
(
gen_random_uuid(),
'OPC # 0017',
'SSE progress stream: Worker → RabbitMQ → API → browser',
'Implemented a real-time Server-Sent Events pipeline. The Worker publishes step progress to RabbitMQ, the API consumes and streams events via SSE, and the browser receives live updates without polling.',
'Feature',
'Done',
'High',
'amadzarak',
NOW(), NOW()
),
(
gen_random_uuid(),
'OPC # 0018',
'Frontend Diagnostics tab with full stack traces from worker',
'Added a Diagnostics tab to the frontend that displays structured error messages and full stack traces forwarded from the Worker service, making provisioning failures debuggable directly in the UI.',
'Feature',
'Done',
'Medium',
'amadzarak',
NOW(), NOW()
),
(
gen_random_uuid(),
'OPC # 0019',
'Enforce LF line endings for *.sh and *.hcl via .gitattributes',
'Added .gitattributes rules to enforce LF line endings for all *.sh and *.hcl files. Prevents CRLF issues from reappearing when contributors commit from Windows machines.',
'Tech Debt',
'Done',
'Low',
'amadzarak',
NOW(), NOW()
);