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
664 lines
28 KiB
Markdown
664 lines
28 KiB
Markdown
# 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: 1–16 (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:
|
||
|
||
```bash
|
||
npm --prefix sdk run openapi:generate
|
||
```
|
||
|
||
Regenerate EE specs:
|
||
|
||
```bash
|
||
npm --prefix sdk run openapi:generate -- --edition ee
|
||
```
|
||
|
||
Placeholder scan pattern:
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
git status --short
|
||
```
|
||
|
||
Expected persistent unstaged file:
|
||
|
||
```text
|
||
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
|
||
|
||
```bash
|
||
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
|
||
|
||
```bash
|
||
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
|
||
|
||
```bash
|
||
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 (F013–F024, T006–T012)
|
||
|
||
### 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.
|