chore: ai, public course and other ui improvements

This commit is contained in:
Rotimi Best
2026-05-09 06:05:03 +01:00
parent 5717dd8004
commit c31ad63955
318 changed files with 20668 additions and 4788 deletions
+383
View File
@@ -0,0 +1,383 @@
---
name: Public API with Organization-Scoped Automation Keys
overview: Build the public API on top of the shipped organization automation foundation: the `/org/[slug]/automation` section already exists, MCP is live, `/automation/api` and `/automation/zapier` exist as placeholder pages, and org-scoped automation keys already exist in the backend. This PRD updates the remaining work to ship the actual public API experience and docs.
todos:
- id: confirm-existing-foundation
content: Confirm and preserve the shipped automation foundation (`Automation` nav, `/org/[slug]/automation` redirect, MCP page, organization automation key backend)
status: completed
- id: org-automation-foundation
content: Keep using `organization_api_key` and `/organization/automation/*` as the shared automation-key foundation for MCP, API, and Zapier
status: completed
- id: mcp-page-reference
content: Use the existing MCP implementation as the structural reference for the API page (route shell, server load, feature API class, feature page component, translations)
status: completed
- id: agents-guidance
content: Ensure all implementation in this initiative follows `AGENTS.md`
status: completed
- id: api-tab-page
content: Replace the placeholder `/org/[slug]/automation/api` page with a real API page that follows the MCP page pattern
status: completed
- id: api-tab-server-load
content: Add `/org/[slug]/automation/api/+page.server.ts` to load API key and usage data using the existing organization automation endpoints
status: completed
- id: api-tab-copy
content: Add API-specific translations and content for docs links, usage messaging, and key management states
status: completed
- id: v1-validation-schemas
content: Add public API input/output validation schemas on top of the existing automation-key schemas
status: completed
- id: v1-services
content: Create versioned public API services for courses and audience/students
status: completed
- id: v1-routes
content: Create and register `/v1` public API routes authenticated by organization automation keys
status: completed
- id: public-api-scopes
content: Finalize the public API scope model and middleware requirements for `api` and `zapier` automation keys
status: completed
- id: tests
content: Add API tests for automation auth, `/v1` routes, and contract coverage
status: completed
- id: openapi-contracts
content: Ensure all public API routes are represented in generated OpenAPI output
status: completed
- id: openapi-publish
content: Regenerate and upload the latest OpenAPI spec via `upload-openapi-spec.ts`
status: completed
- id: docs-openapi-integration
content: Add the public API docs experience in `apps/docs`
status: completed
- id: build-verify
content: Build and verify API and docs packages after implementation
status: completed
isProject: false
---
# Public API with Organization-Scoped Automation Keys
## Status
- Done (shipped)
## Goal
Ship a versioned public API on top of the existing organization automation platform. The current codebase already supports shared org-scoped automation keys and a dedicated Automation section in `/org`; this PRD now focuses on the remaining API product work rather than re-specifying the already-shipped foundation.
## Implementation Guardrails
- All implementation in this initiative must follow [AGENTS.md](../../AGENTS.md).
- Do not design this as a brand-new standalone automation surface. Follow the existing patterns already used by the MCP implementation.
- For dashboard work, the API page must mirror the MCP structure:
- route shell under `apps/dashboard/src/routes/org/[slug]/automation/*`
- server-side data loading in `+page.server.ts`
- state and mutations in `apps/dashboard/src/lib/features/automation/api/automation.svelte.ts`
- request/response types in `apps/dashboard/src/lib/features/automation/utils/types.ts`
- page composition in `apps/dashboard/src/lib/features/automation/pages/api.svelte`
- Do not define new dashboard types inside `.svelte.ts` files. Keep feature types in `utils/types.ts` and infer them from the API client.
- Keep user-facing copy in `apps/dashboard/src/lib/utils/translations/en.json`.
## Current State Confirmed in Code
### Org navigation and routes
These pieces already exist and should be treated as the current baseline:
- `apps/dashboard/src/lib/features/ui/navigation/org-navigation.ts`
- contains an admin-only `Automation` section under `/org/[slug]/automation`
- exposes nested entries for `MCP`, `Zapier`, and `API`
- `apps/dashboard/src/routes/org/[slug]/automation/+page.ts`
- redirects `/org/[slug]/automation` to `/org/[slug]/automation/mcp`
- `apps/dashboard/src/routes/org/[slug]/automation/mcp/+page.svelte`
- shipped MCP route shell using `Page.Root`, `Page.Header`, and `Page.Body`
- `apps/dashboard/src/routes/org/[slug]/automation/mcp/+page.server.ts`
- already loads automation keys and usage for `type=mcp`
- `apps/dashboard/src/routes/org/[slug]/automation/api/+page.svelte`
- already exists, but is currently a placeholder
- `apps/dashboard/src/routes/org/[slug]/automation/zapier/+page.svelte`
- already exists, but is currently a placeholder
### Frontend automation feature foundation
These pieces already exist and should be reused:
- `apps/dashboard/src/lib/features/automation/api/automation.svelte.ts`
- shared automation API class for list/create/revoke/rotate
- `apps/dashboard/src/lib/features/automation/utils/types.ts`
- shared request and response inference types
- `apps/dashboard/src/lib/features/automation/pages/mcp.svelte`
- the current reference implementation for page structure and composition
- `apps/dashboard/src/lib/features/automation/pages/api.svelte`
- currently renders only a coming-soon callout
- `apps/dashboard/src/lib/utils/translations/en.json`
- already contains automation navigation and MCP copy
### Backend automation-key foundation
This work is already implemented and should not be re-invented as a separate `/api-key` system:
- `packages/db/src/schema.ts`
- already defines `organization_api_key`
- already defines `organization_automation_usage`
- `packages/utils/src/validation/organization/automation-key.ts`
- already defines key types: `mcp`, `api`, `zapier`
- already defines scopes, query params, creation payload, and param validation
- `packages/db/src/queries/organization/automation-key.ts`
- already handles persistence for organization automation keys
- `apps/api/src/services/organization/automation-key.ts`
- already handles secret generation, hashing, creation, revoke, rotate, and auth
- `apps/api/src/routes/organization/automation.ts`
- already exposes:
- `GET /organization/automation/usage`
- `GET /organization/automation/keys`
- `POST /organization/automation/keys`
- `DELETE /organization/automation/keys/:keyId`
- `POST /organization/automation/keys/:keyId/rotate`
### Important correction to the old PRD
The old PRD assumed:
- a brand-new Automation page still needed to be created
- Automation should be one page with internal tabs
- a standalone `/api-key` backend should be introduced
- `Webhooks` was one of the primary tabs
That is no longer accurate.
The current product structure is:
- org navigation owns the Automation section
- Automation is split into nested routes: `mcp`, `zapier`, and `api`
- the shared backend lives under `/organization/automation/*`
- MCP is the shipped reference page
- `api` and `zapier` are present as placeholder pages
## Existing Foundation to Build On
### 1. Shared Automation Keys
The public API must reuse the existing organization-scoped automation-key model.
Current model:
- table: `organization_api_key`
- key types: `mcp`, `api`, `zapier`
- key prefixes: generated from the actual secret prefix
- auth: bearer token via the existing automation-key service/middleware path
- rotation and revocation: already implemented
- usage tracking: already implemented in `organization_automation_usage`
Design requirement:
- do not introduce a second key table or a second dashboard key-management surface
- do not reintroduce the older `/api-key` route design from the original PRD
- build the public API on the existing `organization/automation` contracts unless there is a deliberate migration plan
### 2. Dashboard Information Architecture
The Automation product is already organized as nested org routes, not a tabbed single-page shell.
Required route structure:
- `/org/[slug]/automation`
- redirect only
- `/org/[slug]/automation/mcp`
- existing reference implementation
- `/org/[slug]/automation/api`
- target page for public API setup and management
- `/org/[slug]/automation/zapier`
- separate placeholder or future implementation
Design requirement:
- keep the org sidebar/navigation pattern unchanged
- do not replace nested routes with a new internal tabs container for top-level Automation navigation
- if tabs are used inside a page, use them only for local subcontent, the way MCP uses setup tabs for client snippets
## Remaining Product Scope
### 3. API Page in Dashboard
The next dashboard milestone is to replace the placeholder API page with a real implementation.
### Target route files
- `apps/dashboard/src/routes/org/[slug]/automation/api/+page.svelte`
- `apps/dashboard/src/routes/org/[slug]/automation/api/+page.server.ts`
- `apps/dashboard/src/lib/features/automation/pages/api.svelte`
- `apps/dashboard/src/lib/features/automation/api/automation.svelte.ts`
- `apps/dashboard/src/lib/features/automation/utils/types.ts`
- `apps/dashboard/src/lib/utils/translations/en.json`
### Required structure
The API page must follow the same structural pattern already used by MCP:
1. Route shell:
- use `Page.Root`, `Page.Header`, `Page.HeaderContent`, `Page.Title`, and `Page.Body`
- set the page title from `automation.tabs.api`
- use an API-specific subtitle, not the generic coming-soon copy
2. Server load:
- add `+page.server.ts`
- load key data with `classroomio.organization.automation.keys.$get({ query: { type: 'api' } })`
- load usage data with `classroomio.organization.automation.usage.$get({ query: { type: 'api' } })`
- hydrate the shared `automationApi` store the same way MCP currently does
3. Feature page:
- keep composition in `apps/dashboard/src/lib/features/automation/pages/api.svelte`
- mirror the MCP page layout style and sectioning
- do not leave this page as a single callout
### Required API page sections
The real API page should include the following, using the MCP page as the UX baseline:
- admin permission callout for non-admin users
- usage cards or equivalent summary block for API-specific limits
- API key table filtered to `type === 'api'`
- create key flow
- rotate key flow
- revoke key flow
- one-time secret reveal after creation or rotation
- docs/discovery section with a link to the public API documentation
- API-specific setup guidance
### Reuse requirements
- reuse `automationApi` instead of introducing a separate API-only dashboard client
- reuse shared automation types in `utils/types.ts`
- add new helper utilities only if the API page needs API-specific setup snippets or docs helpers
### 4. Public API Routes
The actual public API is still pending.
### Router structure
Create:
- `apps/api/src/routes/v1/index.ts`
- `apps/api/src/routes/v1/courses.ts`
- `apps/api/src/routes/v1/audience.ts`
Register in `apps/api/src/app.ts` as:
```typescript
.route('/public-api/v1', v1Router)
```
### Authentication model
All `/public-api/v1` routes must authenticate with organization automation keys.
Requirements:
- use the existing automation-key authentication path
- require `type: 'api'` or an equivalent scope model that intentionally permits public API access
- document and enforce scopes clearly
- do not rely on session auth for `/public-api/v1`
### Planned endpoint groups
Initial public API surface:
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/public-api/v1/courses` | List organization courses |
| POST | `/public-api/v1/courses` | Create a course |
| GET | `/public-api/v1/courses/:courseId` | Get course details |
| PUT | `/public-api/v1/courses/:courseId` | Update a course |
| DELETE | `/public-api/v1/courses/:courseId` | Soft-delete a course |
| GET | `/public-api/v1/courses/:courseId/export` | Export course content as JSON |
| GET | `/public-api/v1/courses/:courseId/students` | List enrolled students |
| GET | `/public-api/v1/audience` | List organization audience members |
| POST | `/public-api/v1/audience` | Add a student to the organization |
| POST | `/public-api/v1/audience/assign-courses` | Assign one or more audience members to one or more courses |
| GET | `/public-api/v1/audience/:studentId` | Get student details |
| PUT | `/public-api/v1/audience/:studentId` | Update student details |
| DELETE | `/public-api/v1/audience/:studentId` | Remove a student from the organization |
Enrollment decision:
- keep only the audience assignment endpoint for enrollment
- do not add a separate course-centric enrollment route such as `POST /public-api/v1/courses/:courseId/students`
- a single audience member plus a single course in `POST /public-api/v1/audience/assign-courses` covers the single-enrollment case
- multiple audience members and multiple courses in the same payload cover the bulk-assignment case
### 5. Validation and Services
Add public API schemas and services on top of the existing automation-key foundation.
Target files:
- `packages/utils/src/validation/...`
- `apps/api/src/services/v1/course.ts`
- `apps/api/src/services/v1/audience.ts`
Requirements:
- follow the route/service/validation split defined in `AGENTS.md`
- each route must return a single response type shape
- keep business logic in services, not routes
- reuse existing DB queries where possible
### 6. OpenAPI and Docs
The backend already has OpenAPI infrastructure. The remaining work is to ensure the new public API is included and discoverable.
### OpenAPI requirements
- all new `/public-api/v1/*` routes must be documented with the existing Hono OpenAPI patterns
- request params, query, body, success, and error responses must be declared
- avoid undocumented public API routes
### Spec publishing
Use the existing script:
- `apps/api/scripts/upload-openapi-spec.ts`
Required flow after API changes:
1. Implement or update routes and schemas.
2. Run `pnpm --filter @cio/api upload:openapi`.
3. Verify the latest spec includes the new routes.
### Docs integration
Add the public API docs experience in `apps/docs`.
Target tasks:
1. Add the API docs page or route.
2. Wire it to the published OpenAPI source.
3. Add docs navigation for API.
4. Verify the docs build still passes.
### 7. Testing
Add tests for:
- organization automation key auth behavior relevant to public API access
- `/v1/courses`
- `/v1/audience`
- OpenAPI contract inclusion for public API routes
Use Hono app-level testing where possible.
### 8. Build and Verification
Required verification commands after implementation:
1. `pnpm --filter @cio/api build`
2. `pnpm --filter @cio/api upload:openapi`
3. `pnpm --filter @cio/docs build`
Manual verification:
1. `/org/[slug]/automation` still redirects to `/org/[slug]/automation/mcp`
2. `/org/[slug]/automation/api` now renders the real API page rather than the placeholder
3. API key creation, rotation, and revoke flows work for `type=api`
4. `/public-api/v1/*` routes respond under the new base path
5. docs navigation exposes the public API docs entry