Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
411 lines
12 KiB
JSON
411 lines
12 KiB
JSON
[
|
|
{
|
|
"id": "F001",
|
|
"description": "PRECONDITION (already in working tree as licval WIP, verification-only \u2014 do NOT rebuild): admin password is set at install. server/scripts/create-tenant.ts reads INITIAL_ADMIN_PASSWORD (and args.password) and threads it through createTenantComplete \u2192 createAdminUser, which uses input.password ?? generateSecurePassword() (ee/server/src/lib/testing/tenant-creation.ts). create-tenant.ts also initializes tenant_settings (onboarding pending) and honors DB_HOST/DB_PORT/DB_USER_ADMIN. INITIAL_TENANT_ID lands in these same two files.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"9"
|
|
]
|
|
},
|
|
{
|
|
"id": "F002",
|
|
"description": "Migration: alter claim_codes.entitlement_id to NULLABLE (alga-license/migrations/03 baseline is NOT NULL). New numbered migration, up + down.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"7"
|
|
]
|
|
},
|
|
{
|
|
"id": "F003",
|
|
"description": "Migration: add claim_codes.tenant_id uuid (NULLABLE, FK \u2192 tenant_registry ON DELETE CASCADE, indexed). Nullable not NOT NULL \u2014 the legacy /claim-codes path + existing rows carry no registry tenant; /register falls back to the body tenant_id for those. (Refinement from PRD \u00a77.)",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"7"
|
|
]
|
|
},
|
|
{
|
|
"id": "F004",
|
|
"description": "db.ts: insertClaimCode accepts tenant_id (required) and entitlement_id (optional/nullable).",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"7"
|
|
]
|
|
},
|
|
{
|
|
"id": "F005",
|
|
"description": "db.ts: getClaimCode + ClaimCodeRow expose tenant_id and nullable entitlement_id.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"7"
|
|
]
|
|
},
|
|
{
|
|
"id": "F006",
|
|
"description": "db.ts: new revokeClaimCodesForTenant(tenantId) \u2014 reissue path for essentials codes that have no entitlement to key on.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"7",
|
|
"8"
|
|
]
|
|
},
|
|
{
|
|
"id": "F007",
|
|
"description": "db.ts: setRegistryTenantInstalled(tenantId) \u2014 set status='installed' + installed_at.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"7",
|
|
"8"
|
|
]
|
|
},
|
|
{
|
|
"id": "F010",
|
|
"description": "/register: source tenant_id from the claim_code row (row.tenant_id), the registry-minted identity, instead of the request body.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"8"
|
|
]
|
|
},
|
|
{
|
|
"id": "F011",
|
|
"description": "/register: keep accepting body tenant_id ONLY as a legacy fallback for pre-registry appliances (registry path ignores it).",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"8"
|
|
]
|
|
},
|
|
{
|
|
"id": "F012",
|
|
"description": "/register: essentials path \u2014 when row.entitlement_id is null, skip license minting AND skip the appliance row (appliances.entitlement_id is NOT NULL and there is nothing to refresh); return { tenant_id, edition }. (Refines the original 'still upsertAppliance'.)",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"8"
|
|
]
|
|
},
|
|
{
|
|
"id": "F013",
|
|
"description": "/register: look up tenant_registry by tenant_id for edition + company_name + contact_email to include in the response.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"8"
|
|
]
|
|
},
|
|
{
|
|
"id": "F014",
|
|
"description": "/register: paid path unchanged \u2014 mint per-appliance license bound aud=tenant_id (registry-sourced), reuse license_sub, return first_jwt + appliance_credential + check_in_url.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"8"
|
|
]
|
|
},
|
|
{
|
|
"id": "F015",
|
|
"description": "RegisterResponse type + payload: add tenant_id, edition, company_name, contact_email; make appliance_credential / first_jwt / check_in_url optional (present only for paid).",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"8"
|
|
]
|
|
},
|
|
{
|
|
"id": "F016",
|
|
"description": "/register: on success, set registry status='installed' + installed_at (F007).",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"8"
|
|
]
|
|
},
|
|
{
|
|
"id": "F020",
|
|
"description": "/register-tenant: new route scaffold guarded by makeServiceAuthHook (service auth), registered in server.ts.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"8",
|
|
"12"
|
|
]
|
|
},
|
|
{
|
|
"id": "F021",
|
|
"description": "/register-tenant: create tenant_registry row via createRegistryTenant (deployment_type=appliance, status=registered) from company/contact/edition; validate edition enum.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"8"
|
|
]
|
|
},
|
|
{
|
|
"id": "F022",
|
|
"description": "/register-tenant: paid tier \u2014 create/link the entitlement (+ stripe_customer_id linkage) for the new tenant.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"8",
|
|
"10"
|
|
]
|
|
},
|
|
{
|
|
"id": "F023",
|
|
"description": "/register-tenant: mint an install code carrying tenant_id (+ entitlement_id when paid) via generateClaimCode + insertClaimCode (F004).",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"8",
|
|
"5"
|
|
]
|
|
},
|
|
{
|
|
"id": "F024",
|
|
"description": "/register-tenant: presign the current ISO and return { tenant_id, install_code, download_url } (RegisterTenant request/response api-types).",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"8",
|
|
"11"
|
|
]
|
|
},
|
|
{
|
|
"id": "F030",
|
|
"description": "/install-codes/reissue: new route scaffold guarded by makeServiceAuthHook.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"8",
|
|
"12"
|
|
]
|
|
},
|
|
{
|
|
"id": "F031",
|
|
"description": "/install-codes/reissue: resolve the registry tenant by contact_email (getRegistryTenantByEmail) or tenant_id (getRegistryTenant); 404 when unknown.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"8"
|
|
]
|
|
},
|
|
{
|
|
"id": "F032",
|
|
"description": "/install-codes/reissue: revoke prior unconsumed codes for that tenant via revokeClaimCodesForTenant (F006) so only the newest code is live.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"8"
|
|
]
|
|
},
|
|
{
|
|
"id": "F033",
|
|
"description": "/install-codes/reissue: mint a fresh install code for the SAME tenant_id (+ current entitlement if any) and a fresh presigned download_url; return { install_code, download_url }.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"8"
|
|
]
|
|
},
|
|
{
|
|
"id": "F040",
|
|
"description": "Presign helper in alga-license: object-store (MinIO) credentials supplied via env vars; mints a time-boxed presigned GET URL for an object key.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"11",
|
|
"16"
|
|
]
|
|
},
|
|
{
|
|
"id": "F041",
|
|
"description": "Appliance release process publishes the current generic ISO to a known object-store key that the presign helper targets.",
|
|
"implemented": false,
|
|
"prdRefs": [
|
|
"11",
|
|
"16"
|
|
]
|
|
},
|
|
{
|
|
"id": "F042",
|
|
"description": "Presigned URL expiry is configurable (claim-code-aligned TTL) and documented.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"11"
|
|
]
|
|
},
|
|
{
|
|
"id": "F050",
|
|
"description": "createTenant (tenant-creation.ts) accepts optional tenantId; when set, tenantInsert.tenant = input.tenantId instead of relying on the gen_random_uuid() default.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"9"
|
|
]
|
|
},
|
|
{
|
|
"id": "F051",
|
|
"description": "Thread tenantId through createTenantComplete (TenantCreationInput) down to createTenant.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"9"
|
|
]
|
|
},
|
|
{
|
|
"id": "F052",
|
|
"description": "server/scripts/create-tenant.ts reads INITIAL_TENANT_ID (env + optional arg) and passes it into createTenantComplete.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"9"
|
|
]
|
|
},
|
|
{
|
|
"id": "F053",
|
|
"description": "Appliance bootstrap (configmap/script that runs create-tenant at first boot) sets INITIAL_TENANT_ID from the redeem result.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"9"
|
|
]
|
|
},
|
|
{
|
|
"id": "F054",
|
|
"description": "INITIAL_TENANT_ID unset \u2192 unchanged DB-generated UUID behavior (additive/safe, no regression for non-registry installs).",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"9"
|
|
]
|
|
},
|
|
{
|
|
"id": "F055",
|
|
"description": "Idempotent install: rerunning create-tenant with the same INITIAL_TENANT_ID no-ops rather than duplicating the tenant/admin (admin-user create already guards on (email, tenant)).",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"9",
|
|
"13"
|
|
]
|
|
},
|
|
{
|
|
"id": "F060",
|
|
"description": "Setup UI: add an 'enter install code' step (alongside admin password) in the appliance first-boot setup flow.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"9",
|
|
"4"
|
|
]
|
|
},
|
|
{
|
|
"id": "F061",
|
|
"description": "Host-service redeem: POST { claim_code, appliance_id } to /register from the install-time consumer (generalize connectAppliance).",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"9"
|
|
]
|
|
},
|
|
{
|
|
"id": "F062",
|
|
"description": "Host-service redeem: parse tenant_id + edition (+ optional license bits) from the richer RegisterResponse (F015).",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"9"
|
|
]
|
|
},
|
|
{
|
|
"id": "F063",
|
|
"description": "Install: run create-tenant with INITIAL_TENANT_ID = redeemed tenant_id (wires F052/F053 to the redeem result).",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"9"
|
|
]
|
|
},
|
|
{
|
|
"id": "F064",
|
|
"description": "Seed license_state with edition for every install (essentials included), so the appliance reads its tier from license_state.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"9"
|
|
]
|
|
},
|
|
{
|
|
"id": "F065",
|
|
"description": "Seed license_state with license_token (first_jwt) + appliance_credential + check_in_url for paid installs (existing connectAppliance write, made token-optional).",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"9"
|
|
]
|
|
},
|
|
{
|
|
"id": "F066",
|
|
"description": "Essentials install: license_state row exists with no token; appliance runs at edition=essentials without erroring on the missing license.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"9"
|
|
]
|
|
},
|
|
{
|
|
"id": "F067",
|
|
"description": "Setup UI surfaces invalid/expired/consumed code errors clearly and points the user to portal re-issue.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"13"
|
|
]
|
|
},
|
|
{
|
|
"id": "F068",
|
|
"description": "Setup UI/host-service blocks install with a clear 'license service unreachable' error when alga-license can't be reached at redeem.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"13"
|
|
]
|
|
},
|
|
{
|
|
"id": "F070",
|
|
"description": "nm-store: registration form collects company, contact name/email, edition (and product_code) for an appliance registration.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"10",
|
|
"4"
|
|
]
|
|
},
|
|
{
|
|
"id": "F071",
|
|
"description": "nm-store: registration submit calls alga-license POST /register-tenant (service-authed) and handles the response.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"10"
|
|
]
|
|
},
|
|
{
|
|
"id": "F072",
|
|
"description": "nm-store: confirmation page shows the install code (the presigned download link is delivered by email).",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"10"
|
|
]
|
|
},
|
|
{
|
|
"id": "F073",
|
|
"description": "nm-store: email the install code + presigned download link to the contact after registration/purchase (primary delivery of the download link).",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"10",
|
|
"11"
|
|
]
|
|
},
|
|
{
|
|
"id": "F074",
|
|
"description": "nm-store: paid tier \u2014 Stripe checkout ordering (registry row at submit; entitlement + code mint on checkout.session.completed).",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"10",
|
|
"16"
|
|
]
|
|
},
|
|
{
|
|
"id": "F075",
|
|
"description": "nm-store: portal 're-issue install code' action (behind portal auth) calls POST /install-codes/reissue and shows the fresh code + link.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"10",
|
|
"5"
|
|
]
|
|
},
|
|
{
|
|
"id": "F076",
|
|
"description": "Docs: update appliance install + licensing docs to describe register \u2192 download \u2192 install \u2192 re-issue (operator-facing).",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"4",
|
|
"15"
|
|
]
|
|
},
|
|
{
|
|
"id": "F077",
|
|
"description": "nm-store alga-license client (src/lib/algaLicenseClient.ts): typed registerTenant() + reissueInstallCode() calling /register-tenant + /install-codes/reissue (Bearer service auth). The transport F071/F075 build on; the registration UI/Stripe/email that call it are still pending.",
|
|
"implemented": true,
|
|
"prdRefs": [
|
|
"10"
|
|
]
|
|
}
|
|
]
|