Hermes 284313f908
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
Initial import of AlgaPSA codebase from PSA server
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz

Source: /opt/alga-psa on psa.joliet.tech
2026-06-22 16:12:17 -05:00

28 KiB
Raw Blame History

SCRATCHPAD: Complete OpenAPI Documentation Coverage

2026-04-24 — Plan Created

Branch / Worktree

  • Worktree: /Users/roberisaacs/alga-psa.worktrees/docs/api-docs-input-output
  • Branch: docs/api-docs-input-output
  • Existing uncommitted local file to avoid: .env.localtest

Current Progress Baseline

  • Completed batches: 116 (80 operations).
  • Latest pushed commit at plan creation: e733631bf docs(openapi): document asset history and automation execution routes.
  • Remaining CE placeholder count: 488.
  • Progress tracker: /tmp/alga-openapi-doc-progress.md.

Required Commands

Regenerate CE/legacy specs:

npm --prefix sdk run openapi:generate

Regenerate EE specs:

npm --prefix sdk run openapi:generate -- --edition ee

Placeholder scan pattern:

python3 - <<'PY'
import json
spec=json.load(open('sdk/docs/openapi/alga-openapi.ce.json'))
items=[]
for path, methods in spec['paths'].items():
  for method, op in methods.items():
    if isinstance(op,dict) and ('generated automatically' in op.get('description','') or (op.get('extensions') or {}).get('x-placeholder')):
      items.append((path,method.upper(),op.get('summary')))
print('remaining', len(items))
for row in items[:50]:
  print(row)
PY

Batch Workflow Decisions

  • Continue in batches of 5 operations.
  • Use subagents for investigation where possible.
  • Preferred model: deepseek/deepseek-v4-pro.
  • Investigators are read-only and should report source evidence, auth/security, tenant behavior, inputs, outputs, statuses, and ID provenance.
  • Main agent writes registrars and generated specs.
  • Commit/push periodically.
  • Do not stage .env.localtest.

Registrar Rules

  • Put domain registrars under server/src/lib/api/openapi/routes/.
  • Import/register new registrars in server/src/lib/api/openapi/index.ts before registerInventoryBackfillRoutes.
  • Manual route registration key is method+path. If manual route is registered before inventory backfill, placeholder is skipped.
  • Prefer actual source behavior over intended behavior when they differ.
  • When source has implementation bugs, document them in descriptions/extensions rather than fixing runtime code.

Current Remaining Placeholder Domains (CE)

Total: 488 placeholders.

Top route families at plan creation:

  • 37 /api/v1/integrations
  • 37 /api/v1/quickbooks
  • 37 /api/v1/webhooks
  • 34 /api/v1/workflows
  • 31 /api/v1/invoices
  • 29 /api/v1/financial
  • 26 /api/v1/users
  • 24 /api/v1/contract-lines
  • 22 /api/v1/teams
  • 21 /api/v1/quotes
  • 19 /api/v1/tags
  • 18 /api/v1/projects
  • 17 /api/v1/time-entries
  • 17 /api/v1/time-sheets
  • 14 /api/v1/automation
  • 14 /api/v1/categories
  • 12 /api/v1/tickets
  • 10 /api/v1/roles
  • 9 /api/v1/clients
  • 8 /api/v1/contacts
  • 8 /api/v1/meta
  • 8 /api/v1/time-periods
  • 7 /api/v1/permissions
  • 7 /api/v1/schedules
  • 4 /api/v1/contracts
  • 4 /api/v1/user
  • 3 /api/v1/client-contract-lines
  • 2 /api/v1/feature-flags
  • 2 /api/v1/contract-line-templates
  • 2 /api/v1/rbac
  • 1 /api/v1/billing-analytics
  • 1 /api/v1/feature-access
  • 1 /api/v1/permission-checks
  • 1 /api/v1/test-auth
  • 1 /api/v1/user-roles

Next Batch at Plan Creation

Batch 17:

  1. GET /api/v1/automation/performance
  2. GET /api/v1/automation/rules
  3. POST /api/v1/automation/rules
  4. POST /api/v1/automation/rules/bulk-execute
  5. POST /api/v1/automation/rules/bulk-status

Known Gotchas Discovered So Far

  • Some v1 asset routes have edge middleware that checks only x-api-key presence, but route files lack a wrapper that sets req.context; these routes can fail with Request context not available. Document actual behavior.
  • Several controllers return v2 HATEOAS links from v1 routes. Document where observed.
  • Some service methods throw generic Error for not-found/invalid state, producing 500 rather than expected 404/400. Document current behavior.
  • Some inventory routes point to missing route files. Document as inventory-only/missing-handler rather than inventing behavior.
  • deepseek/deepseek-v4 failed earlier; deepseek/deepseek-v4-pro is the working provider-qualified model when provider balance is available.

Commit Discipline

Before every commit:

git status --short

Expected persistent unstaged file:

 M .env.localtest

Do not git add .; stage exact registrar/spec/plan files only.

2026-04-24 — Batch 17 Completed (Automation Rules/Performance + Remaining Automation Family)

Scope completed

  • Documented all remaining placeholder automation endpoints in server/src/lib/api/openapi/routes/automation.ts:
    • GET /api/v1/automation/performance
    • GET /api/v1/automation/rules
    • POST /api/v1/automation/rules
    • POST /api/v1/automation/rules/bulk-execute
    • POST /api/v1/automation/rules/bulk-status
    • DELETE /api/v1/automation/rules/{id}
    • GET /api/v1/automation/rules/{id}
    • PUT /api/v1/automation/rules/{id}
    • POST /api/v1/automation/rules/{id}/execute
    • GET /api/v1/automation/statistics
    • GET /api/v1/automation/templates
    • POST /api/v1/automation/templates
    • GET /api/v1/automation/templates/{id}
    • POST /api/v1/automation/templates/{id}/use

Key source-grounded decisions (with rationale)

  • Documented service/controller mismatch where manualExecutionSchema requires automation_rule_id in request body but execution uses path /rules/{id}. Kept this explicit in schema/description to avoid hiding runtime behavior.
  • Documented known 500-vs-404/400 gaps where AutomationService throws generic Error for not-found or invalid-state conditions.
  • Documented query-array parsing gap on performance route because controller query parsing (validateQueryParams) maps URL params to string values while schema expects arrays for rule_ids and metrics.
  • Preserved tenant/RBAC metadata using base-controller auth flow (x-api-key + optional x-tenant-id, hasPermission against resource automation).

Commands / runbook executed

npm --prefix sdk run openapi:generate
npm --prefix sdk run openapi:generate -- --edition ee
python3 <placeholder scan script for CE+EE targeted automation ops + remaining counts>

Validation results

  • CE targeted automation placeholder check: all 14 automation operations now non-placeholder.
  • EE targeted automation placeholder check: all 14 automation operations now non-placeholder.
  • Remaining placeholder counts after batch:
    • CE: 474 (down from 488)
    • EE: 482

Updated next cursor

  • Next unresolved CE operations:
    1. GET /api/v1/billing-analytics/overview
    2. GET /api/v1/contract-lines
    3. POST /api/v1/contract-lines
    4. DELETE /api/v1/contract-lines/bulk
    5. POST /api/v1/contract-lines/bulk

Gotchas reinforced

  • OpenAPI registry request bodies must be registered as request: { body: { schema: ... } }; passing the schema directly (body: Schema) causes zod-to-openapi generation failure.

2026-04-24 — Contract Line/Template Family Completed (F002)

Scope completed

  • Added new registrar: server/src/lib/api/openapi/routes/contractLines.ts.
  • Imported and registered it before inventory backfill in server/src/lib/api/openapi/index.ts.
  • Documented all 26 previously-placeholder operations across:
    • /api/v1/contract-lines
    • /api/v1/contract-lines/{id} and subresources (activation, analytics, copy, fixed-config, services, usage-metrics)
    • /api/v1/contract-lines/bulk + explicit bulk subpaths
    • /api/v1/contract-line-templates
    • /api/v1/contract-line-templates/{id}/create-contract-line

Key decisions / discovered gaps

  • These controllers depend on requireRequestContext(req) but the global middleware only checks x-api-key presence for /api/* and does not populate request context. Documented as current auth wiring gap (x-request-context-wiring-gap).
  • POST /api/v1/contract-lines/{id}/copy currently uses source_contract_line_id from body and does not consume the path id.
  • POST /api/v1/contract-line-templates/{id}/create-contract-line currently validates/uses body template_id and does not consume the path id.
  • GET /api/v1/contract-lines/{id}/services/{serviceId} currently delegates to getContractLineServices() and returns full service list for {id}; serviceId is effectively ignored in GET behavior.

Validation results

  • CE contract-line/template placeholder check: all 26 operations are non-placeholder.
  • EE contract-line/template placeholder check: all 26 operations are non-placeholder.
  • Remaining placeholders after this pass:
    • CE: 448
    • EE: 456

Commands executed

npm --prefix sdk run openapi:generate
npm --prefix sdk run openapi:generate -- --edition ee
python3 <targeted CE/EE contract-line placeholder checks + global counts>

Next cursor (CE)

  1. GET /api/v1/billing-analytics/overview
  2. GET /api/v1/categories/analytics
  3. POST /api/v1/categories/bulk/delete
  4. GET /api/v1/categories/search
  5. DELETE /api/v1/categories/service/{id}

2026-04-24 — Category Family Completed (F003)

Scope completed

  • Extended server/src/lib/api/openapi/routes/serviceCategories.ts to document all previously-placeholder category operations:
    • GET /api/v1/categories/analytics
    • POST /api/v1/categories/bulk/delete
    • GET /api/v1/categories/search
    • DELETE|GET|PUT /api/v1/categories/service/{id}
    • GET|POST /api/v1/categories/ticket
    • POST /api/v1/categories/ticket/move
    • GET /api/v1/categories/ticket/tree
    • GET /api/v1/categories/ticket/tree/{boardId}
    • DELETE|GET|PUT /api/v1/categories/ticket/{id}

Key source-grounded notes

  • Permission resource is dynamic for search/analytics/bulk delete endpoints (billing_settings for service categories, ticket_settings otherwise).
  • GET /api/v1/categories/ticket/tree currently derives board id from URL last segment; on this route it passes literal tree to service (implementation quirk documented).
  • Tree-by-board route currently works because the final path segment is the board id, even though controller still parses from URL rather than params.

Validation

  • CE category placeholder set: all targeted operations are non-placeholder.
  • EE category placeholder set: all targeted operations are non-placeholder.
  • Remaining placeholder counts after this pass:
    • CE: 434
    • EE: 442

Next cursor (CE)

  1. GET /api/v1/billing-analytics/overview
  2. GET /api/v1/clients
  3. POST /api/v1/clients
  4. GET /api/v1/clients/stats
  5. DELETE /api/v1/clients/{id}

2026-04-24 — Client/Contact Family Completed (F004)

Scope completed

  • Added registrar: server/src/lib/api/openapi/routes/clientsContacts.ts.
  • Registered in server/src/lib/api/openapi/index.ts before inventory backfill.
  • Documented all 20 previously-placeholder operations under:
    • /api/v1/clients*
    • /api/v1/contacts*
    • /api/v1/client-contract-lines*

Key source-grounded notes

  • Client/contact custom routes (stats, search, export, nested client subresources) perform explicit API key validation in-controller and set request context directly.
  • Client-contract-line routes reuse ApiContractLineController request-context-dependent methods; documented current request-context wiring gap and TODO-stub behavior for list endpoint.
  • Contact export can return CSV file response when format=csv; documented this response-mode distinction.

Validation

  • CE placeholder check for the full client/contact/client-contract-line set: all operations are non-placeholder.
  • EE placeholder check for the same set: all operations are non-placeholder.
  • Remaining placeholder counts after this pass:
    • CE: 414
    • EE: 422

Next cursor (CE)

  1. GET /api/v1/billing-analytics/overview
  2. POST /api/v1/feature-access
  3. GET /api/v1/feature-flags
  4. POST /api/v1/feature-flags
  5. POST /api/v1/financial/billing/calculate

2026-04-24 — Financial/Invoice/Billing-Analytics Family Completed (F005)

Scope completed

  • Added registrar: server/src/lib/api/openapi/routes/financialInvoices.ts.
  • Registered in server/src/lib/api/openapi/index.ts before inventory backfill.
  • Documented all previously-placeholder operations under:
    • /api/v1/billing-analytics/overview
    • /api/v1/financial/*
    • /api/v1/invoices/*

Key source-grounded decisions / gaps documented

  • GET /api/v1/billing-analytics/overview maps to ApiContractLineController.getBillingOverviewAnalytics() and currently requires req.context without route-level auth wiring; documented x-request-context-wiring-gap.
  • Multiple /api/v1/financial/* routes are currently wired to generic ApiFinancialController.list/create/update/getById/delete methods (transaction-oriented) rather than route-name-specific resources (payment-methods, tax/rates, financial/invoices/{id}/*); documented as route-to-controller mismatches.
  • POST /api/v1/financial/bulk/transactions and POST /api/v1/financial/bulk/credits currently return 501 Not implemented; documented as implementation gaps.
  • Recurring invoice template routes include TODO stubs (list returns empty array, update synthetic response, delete direct 204); documented explicitly.
  • GET /api/v1/invoices/{id}/pdf returns redirect behavior (307) when download_url exists; documented as redirect endpoint.

Validation / tests completed in this pass

  • T001 completed: CE placeholder scan for the F005 route family (ce_f005_remaining = 0).
  • T002 completed: EE placeholder scan for the same family (ee_f005_remaining = 0).
  • T003 completed: npm --prefix sdk run openapi:generate succeeded.
  • T004 completed: npm --prefix sdk run openapi:generate -- --edition ee succeeded.
  • T005 completed: verified registerFinancialInvoiceRoutes() is imported and called in openapi/index.ts before registerInventoryBackfillRoutes().

Remaining placeholder counts after this pass

  • CE: 353
  • EE: 361

Next cursor (CE)

  1. POST /api/v1/feature-access
  2. GET /api/v1/feature-flags
  3. POST /api/v1/feature-flags
  4. GET /api/v1/integrations/quickbooks/accounts
  5. GET /api/v1/integrations/quickbooks/accounts/mappings

Commands / runbook executed

npm --prefix sdk run openapi:generate
npm --prefix sdk run openapi:generate -- --edition ee
python3 <CE and EE placeholder scans for F005 family + global counts>

2026-04-24 — QuickBooks Duplicate Families Completed (F006)

Scope completed

  • Added registrar: server/src/lib/api/openapi/routes/quickbooksV1.ts.
  • Registered in server/src/lib/api/openapi/index.ts before inventory backfill.
  • Documented all previously-placeholder routes in both v1 QuickBooks families:
    • /api/v1/integrations/quickbooks/*
    • /api/v1/quickbooks/*

Alias verification (T008)

  • Verified both families map method-for-method to the same ApiQuickBooksController handler methods.
  • Distinction documented in operation descriptions/extensions:
    • /api/v1/integrations/quickbooks/*: route files generally wrap controller calls in explicit try/catch with handleApiError.
    • /api/v1/quickbooks/*: route files generally bind controller handlers directly (export const GET = controller.method()).
  • Since controller methods already return handleApiError on failure, current runtime behavior is functionally aliased despite route-wrapper style differences.

Key source-grounded implementation notes captured

  • Controller authenticates via x-api-key + optional x-tenant-id, then RBAC checks against resource quickbooks with actions read|write|admin.
  • Multiple handler methods intentionally return temporary/stub payloads or TODO behavior (for example connection refresh, mapping deletes, sync cancel, account/tax mapping reads); these gaps are called out in descriptions.

Validation / tests completed in this pass

  • T003 and T004 rerun successfully:
    • npm --prefix sdk run openapi:generate
    • npm --prefix sdk run openapi:generate -- --edition ee
  • T008 completed:
    • CE QuickBooks placeholder check: ce_quickbooks_remaining = 0
    • EE QuickBooks placeholder check: ee_quickbooks_remaining = 0

Remaining placeholder counts after this pass

  • CE: 279
  • EE: 287

Next cursor (CE)

  1. POST /api/v1/feature-access
  2. GET /api/v1/feature-flags
  3. POST /api/v1/feature-flags
  4. GET /api/v1/quotes
  5. POST /api/v1/quotes

2026-04-24 — Webhook Family Completed (F007)

Scope completed

  • Added registrar: server/src/lib/api/openapi/routes/webhooks.ts.
  • Registered in server/src/lib/api/openapi/index.ts before inventory backfill.
  • Documented all previously-placeholder webhook routes under /api/v1/webhooks* (37 operations).

Key source-grounded wiring notes documented

  • /api/v1/webhooks/search route currently calls ApiWebhookController.list() (not search()); documented as route-to-controller mismatch.
  • /api/v1/webhooks/templates/{id} GET|PUT|DELETE routes currently call generic webhook getById|update|delete methods; documented as template-route wiring mismatch.
  • Global subscription routes (/api/v1/webhooks/subscriptions GET|POST) call methods that require webhook {id} path extraction; current behavior yields UUID validation failure for literal subscriptions path segment.
  • Several controller paths intentionally return stub/TODO responses (health checks, validation, secret rotation, template/subscription helpers, delivery detail helpers); these are explicitly called out in descriptions/extensions.

Validation results

  • CE webhook placeholder check: ce_webhooks_remaining = 0.
  • EE webhook placeholder check: ee_webhooks_remaining = 0.
  • Regeneration commands succeeded:
    • npm --prefix sdk run openapi:generate
    • npm --prefix sdk run openapi:generate -- --edition ee

Remaining placeholder counts after this pass

  • CE: 242
  • EE: 250

Next cursor (CE)

  1. POST /api/v1/feature-access
  2. GET /api/v1/feature-flags
  3. POST /api/v1/feature-flags
  4. GET /api/v1/quotes
  5. POST /api/v1/quotes

2026-04-24 — Workflow Family Completed (F008)

Scope completed

  • Added registrar: server/src/lib/api/openapi/routes/workflowsV1.ts.
  • Registered in server/src/lib/api/openapi/index.ts before inventory backfill.
  • Documented all previously-placeholder /api/v1/workflows* operations (34 routes).

Source-grounded findings and decisions

  • There are no server/src/app/api/v1/workflows/**/route.ts handlers in this worktree.
  • The inventory placeholders for /api/v1/workflows* were documented explicitly as inventory-only/missing-handler routes rather than inventing behavior.
  • Descriptions now point to existing workflow APIs under /api/workflow-definitions, /api/workflow-runs, and /api/workflow/events to avoid ambiguity.

Validation / tests completed in this pass

  • CE workflow placeholder check: ce_workflows_remaining = 0.
  • EE workflow placeholder check: ee_workflows_remaining = 0.
  • Regeneration commands succeeded:
    • npm --prefix sdk run openapi:generate
    • npm --prefix sdk run openapi:generate -- --edition ee
  • T009 completed by documenting webhook family security/payload behavior and workflow family missing-handler reality with security/missing-route behavior.

Remaining placeholder counts after this pass

  • CE: 208
  • EE: 216

Next cursor (CE)

  1. POST /api/v1/feature-access
  2. GET /api/v1/feature-flags
  3. POST /api/v1/feature-flags
  4. GET /api/v1/quotes
  5. POST /api/v1/quotes

2026-04-24 — Access Control/User/Role/Permission/Team Families Completed (F009)

Scope completed

  • Added registrar: server/src/lib/api/openapi/routes/accessControlUsers.ts.
  • Registered it in server/src/lib/api/openapi/index.ts before inventory backfill.
  • Documented all previously-placeholder operations across:
    • /api/v1/users*
    • /api/v1/user-roles
    • /api/v1/roles*
    • /api/v1/permissions*
    • /api/v1/permission-checks
    • /api/v1/rbac/*
    • /api/v1/teams*

Key source-grounded notes / gaps documented

  • GET /api/v1/rbac/audit is currently a hardcoded 501 stub route and does not call an RBAC controller.
  • POST /api/v1/users/bulk/create currently delegates to ApiUserController.create() (single-user schema/behavior), not bulk-create logic.
  • PUT /api/v1/users/bulk/deactivate currently delegates to ApiUserController.update() and fails UUID path extraction because the route segment bulk is treated as {id}.
  • POST /api/v1/users/{id}/teams currently delegates to ApiUserController.create() (create-user behavior), not team membership creation.
  • DELETE /api/v1/users/{id}/teams/{teamId} currently delegates to ApiUserController.delete(); teamId is ignored and operation acts on user id.
  • GET /api/v1/teams/hierarchy currently parses team id from URL tail and uses literal hierarchy as id on this route.
  • DELETE /api/v1/teams/{id}/permissions/{permissionId} revokes by permission id and does not use team id in service call.

Validation

  • CE F009 placeholder check: ce_f009_remaining = 0.
  • EE F009 placeholder check: ee_f009_remaining = 0.
  • Regeneration commands succeeded:
    • npm --prefix sdk run openapi:generate
    • npm --prefix sdk run openapi:generate -- --edition ee

Remaining placeholder counts after this pass

  • CE: 139
  • EE: 147

Next cursor (CE)

  1. POST /api/v1/feature-access
  2. GET /api/v1/feature-flags
  3. POST /api/v1/feature-flags
  4. GET /api/v1/quotes
  5. POST /api/v1/quotes

2026-04-24 — Project/Ticket/Tag/Schedule/Time Families Completed (F010)

Scope completed

  • Added registrar: server/src/lib/api/openapi/routes/workManagementV1.ts.
  • Registered it in server/src/lib/api/openapi/index.ts before inventory backfill.
  • Documented all previously-placeholder operations across:
    • /api/v1/projects*
    • /api/v1/tickets*
    • /api/v1/tags*
    • /api/v1/schedules*
    • /api/v1/time-entries*
    • /api/v1/time-sheets*
    • /api/v1/time-periods*

Key source-grounded notes / wiring gaps documented

  • GET /api/v1/schedules/search and GET /api/v1/schedules/{id}/conflicts currently delegate to ApiTimeSheetController.list().
  • GET /api/v1/schedules/{id} currently delegates to ApiTimeSheetController.getById() (time-sheet read path) instead of schedule-specific getter.
  • GET /api/v1/time-periods/current currently delegates to ApiTimeSheetController.list().
  • POST /api/v1/time-periods/{id}/close and /reopen currently delegate to ApiTimeSheetController.update() (time-sheet update path).
  • Several time-sheet subroutes are currently wired to generic handlers rather than route-intent-specific methods:
    • POST /api/v1/time-sheets/bulk -> list()
    • GET /api/v1/time-sheets/search -> list()
    • POST /api/v1/time-sheets/{id}/add-entry -> create()
    • GET /api/v1/time-sheets/{id}/entries -> list()
    • POST /api/v1/time-sheets/{id}/reject -> update()
    • DELETE /api/v1/time-sheets/{id}/remove-entry -> delete()
    • GET /api/v1/time-sheets/{id}/summary -> list()

Validation

  • CE F010 placeholder check: ce_f010_remaining = 0.
  • EE F010 placeholder check: ee_f010_remaining = 0.
  • Regeneration commands succeeded:
    • npm --prefix sdk run openapi:generate
    • npm --prefix sdk run openapi:generate -- --edition ee

Remaining placeholder counts after this pass

  • CE: 41
  • EE: 49

Next cursor (CE)

  1. POST /api/v1/feature-access
  2. GET /api/v1/feature-flags
  3. POST /api/v1/feature-flags
  4. GET /api/v1/quotes
  5. POST /api/v1/quotes

2026-04-24 — Quotes/Contracts + Meta/Utility Families Completed (F011, F012)

Scope completed

  • Added registrar: server/src/lib/api/openapi/routes/quotesContractsV1.ts.
  • Added registrar: server/src/lib/api/openapi/routes/metaUtilityV1.ts.
  • Added registrar: server/src/lib/api/openapi/routes/eeInventoryOnly.ts (EE-only inventory placeholders).
  • Registered all three in server/src/lib/api/openapi/index.ts before inventory backfill.
  • Documented all previously-placeholder operations under:
    • /api/v1/quotes*
    • /api/v1/contracts*
    • /api/v1/feature-access
    • /api/v1/feature-flags
    • /api/v1/meta/*
    • /api/v1/test-auth
    • /api/v1/user/telemetry-*
    • EE-only inventory placeholders:
      • /api/ext-bundles/*
      • /api/extensions/install-info
      • /api/extensions/registry-db-check
      • /api/extensions/reprovision
      • /api/provisioning/tenants
      • /api/v1/auth/verify

Key source-grounded notes / gaps documented

  • Quote read authorization uses billing-resource authorization context in ApiQuoteController.assertQuoteReadAllowed() while controller CRUD permissions are checked on quote resource; documented this distinction.
  • Contract v1 routes currently mount ApiContractLineController (v2 controller) and call requireRequestContext(req); documented request-context wiring dependency/gap on those paths.
  • Feature flag and telemetry routes are session-oriented (getSession/getCurrentUser) while global /api/* middleware can still require API key presence unless path is explicitly skipped; documented as mixed auth behavior.
  • EE-only placeholder paths that have no handler files in this worktree were converted to explicit inventory-only route docs instead of leaving generated placeholders.

2026-04-24 — Final Validation and Closeout (F013F024, T006T012)

Final placeholder results

  • CE full scan: 0 placeholders.
  • EE full scan: 0 placeholders.

Representative auth/RBAC verification (T006)

Reviewed representative read/mutation flows across major API-key v1 domains and confirmed docs align with source behavior:

  • User domain:
    • Read: ApiUserController.stats() / getPermissions() enforce hasPermission(..., 'user', 'read', ...).
    • Mutation: assignRoles() / changePassword() enforce update checks and contextual constraints.
  • Team domain:
    • Read: ApiTeamController.getMembers() enforces team:read.
    • Mutation: addMember() enforces team:update.
  • Project domain:
    • Read: ApiProjectController.list()/search()/stats() enforce read checks and authorization filtering.
    • Mutation: bulkUpdate()/createPhaseTask() enforce update checks.
  • Ticket domain:
    • Read: ApiTicketController.list()/stats() enforce read checks.
    • Mutation: updateStatus()/updateAssignment() enforce update checks.

Representative billing/financial/invoice verification (T007)

Re-validated representative endpoints in server/src/lib/api/openapi/routes/financialInvoices.ts against source-backed request/response behavior:

  • POST /api/v1/financial/billing/calculate: request body schema registered and required under request.body.schema; response envelope documented as API success/error.
  • Invoice lifecycle request schemas (InvoiceSendBody, InvoiceFinalizeBody, InvoicePaymentBody, bulk schemas) are registered and attached to route request bodies.
  • Financial/invoice responses retain documented envelope patterns (ApiSuccess / ApiPaginated / error structure) and known implementation-gap notes from earlier F005 work.

Commit/staging discipline verification (T010)

  • Before each commit in this pass, git status --short confirmed .env.localtest remained unstaged while intended plan/registrar/spec files were staged explicitly.

Plan consistency review (T012)

Reviewed final alignment among:

  • PRD.md
  • features.json
  • tests.json
  • SCRATCHPAD.md
  • /tmp/alga-openapi-doc-progress.md

Result: all tracked workstreams and acceptance checkpoints are synchronized with final generated OpenAPI state (CE/EE placeholder scans at zero).

Final summary of discovered implementation gaps (F024)

Representative deferred runtime issues captured in OpenAPI docs instead of code fixes:

  • Route-to-controller mismatches on several v1 legacy paths (notably some user/team/time-period/time-sheet/schedule routes).
  • Session-vs-API-key mixed auth behavior on feature flag and telemetry endpoints.
  • Contract v1 routes using v2 controller assumptions (requireRequestContext).
  • Inventory-only EE paths with missing handlers documented as such.

No runtime behavior changes were made as part of this documentation pass.