feat(SPA): screen to manage API keys (PART 2/3)
This commit is contained in:
1 parent
844842fdae
commit
514a082c96
30 files changed
+3844
-83
No files matched your search
@@ -1,6 +1,8 @@
|
||||
# Integration (API reference) and API keys
|
||||
# Integration (API reference)
|
||||
|
||||
Routes: `/integration` and `/integration/api-keys`. Boards: `RenewCMS Screens Back-office.dc.html` (group "Integration") and `RenewCMS Screens API keys.dc.html`. Components: `IntegrationPage.dc.html`, `ApiKeysPage.dc.html`, mounted by `AppFrame`.
|
||||
Route: `/integration`. Component: `IntegrationPage.dc.html`, mounted by `AppFrame`. The API keys sub-page is in `screens/integration-api-keys.md`.
|
||||
|
||||
- **Visual reference:** `source/RenewCMS Screens Back-office.dc.html`, group "Integration", drawn by `source/IntegrationPage.dc.html` (open it in a browser; each state is drawn at desktop and mobile, with a light/dark toggle).
|
||||
|
||||
## Navigation decision
|
||||
Sticky section index on the right (desktop), "Jump to" select (mobile). A reference is read in one scroll and searched with the browser, so tabs would hide content and break find-in-page and deep links; the index keeps one page with anchors and shows position.
|
||||
@@ -13,9 +15,9 @@ Sticky section index on the right (desktop), "Jump to" select (mobile). A refere
|
||||
- Card "API key": "Send `Authorization: Bearer rcms_…`. Requests act as the user who created the key, with that user's role (owner or admin). A key never has more rights than its creator." CodeBlock tabs curl, fetch (GET /v1/auth/me). "Keys start with `rcms_` and are shown in full once, when you create them." Link "Manage API keys".
|
||||
- Note 1: "A key can't create, list or revoke API keys, log in, register, verify or reset a password, or call anything under `/v1/system`. Those routes answer 403 "This action needs a real session." An invalid, unknown, expired or revoked key answers 401, even on public routes, and so does a key whose user was deleted or unverified."
|
||||
- Note 2: "Each key can make 120 requests per minute. Beyond that the API answers 429 with a `Retry-After` header."
|
||||
- Groups: Articles (7), Media (6), Users and invites (6), Settings (1), Session only (12 routes, 3 sub-groups). Session-only banner: "These routes need a signed-in browser session. With an API key they answer 403 "This action needs a real session.""
|
||||
- Errors: table 400, 401, 403, 404, 409, 422, 429, 500 plus the JSON body.
|
||||
- Notes: image URL prefix, CORS (existing copy), and "Article routes accept `?format=html` or `?format=markdown` to choose how `body` is returned."
|
||||
- Groups: Articles (7), Media (6), Users and invites (6), Settings (1), Session only (12 routes, 3 sub-groups; every `/v1/system` route is in this group). Session-only banner: "These routes need a signed-in browser session. With an API key they answer 403 "This action needs a real session.""
|
||||
- Errors: "Every error is a plain-text body with a single sentence. The status code is in the HTTP status line, and the Content-Type is text/plain." Table 400, 401, 403, 404, 429, 500 with the real messages below. Sample: a status line plus the text body (`HTTP/1.1 403 Forbidden`, `Content-Type: text/plain`, blank line, `This action needs a real session.`).
|
||||
- Notes: image URL prefix, CORS (existing copy), and "Article routes accept `?format=markdown`, `?format=html` or `?format=json` to choose how `body` is returned. With `json`, `body` is the stored JSON structure. Articles have `body_format: markdown` by default."
|
||||
|
||||
## EndpointCard states
|
||||
- Collapsed (44 px row): method badge, mono path, one-line description, chips, chevron. Desktop is one line; mobile is three (method and path, description, chips).
|
||||
@@ -24,27 +26,57 @@ Sticky section index on the right (desktop), "Jump to" select (mobile). A refere
|
||||
- Chips: access "Public", "Verified user", "Owner only"; key "API key OK" (success soft) or "Session only" (dashed, muted).
|
||||
- Method badges: GET `--ui-bg-inverted`, POST success soft, PATCH warning soft, DELETE error soft. Existing tokens only.
|
||||
|
||||
## Board states (desktop 1440×900, mobile 390×844, light and dark)
|
||||
1 Default · 2 Media group, POST /v1/media/ expanded with curl tab · 3a Base URL copied · 3b CodeBlock copied · 4 Authentication · 5 Session only · 6 Errors · 7 Navigation (index active item Media; mobile select open).
|
||||
## States
|
||||
Desktop 1440×900, mobile 390×844, light and dark. Names are matched exactly by the visual-check script.
|
||||
|
||||
## API keys screen
|
||||
Placement: under Integration (sub-page), because keys exist to call the API and admins can create them; Settings is owner-only today. Session only.
|
||||
- Columns: Name, Key (prefix, mono), Status (active, expired, revoked), Created by (owners only), Created, Last used, Expires, Revoke. Owners see all keys; admins see their own.
|
||||
- Create key modal: Name (required, up to 60, counter), Expiry date (optional, must be in the future). Errors: "Enter a name." / "Use 60 characters or fewer." / "Choose a date in the future."
|
||||
- One-time reveal: warning "You won't be able to see this key again.", monospace key, Copy / Copied, "Closing this window discards the key from the screen. Copy it first." Button "Done".
|
||||
- Revoke: "Revoke this key?" / ""Nightly media import" (rcms_Mq7b…) will stop working right away. Requests that use it answer 401. This can't be undone." Buttons "Keep key", "Revoke key". Toast "Key revoked".
|
||||
- Empty: "No API keys yet" / "Create a key to call the API from a script or service." Error: "Couldn't load your API keys" / "Check your connection and try again."
|
||||
- Note: "Resetting a user's password revokes all of their keys."
|
||||
### 1. Default
|
||||
|
||||
### 2. Group scrolled, one card expanded
|
||||
|
||||
### 3a. Copied: base URL
|
||||
|
||||
### 3b. Copied: CodeBlock
|
||||
|
||||
### 4. Authentication
|
||||
|
||||
### 5. Session only
|
||||
|
||||
### 6. Errors
|
||||
|
||||
### 7. Navigation
|
||||
|
||||
## Error messages
|
||||
Plain text, one sentence. Used in the table and in the per-endpoint error captions.
|
||||
- 400: "The request cannot be processed due to a mismatch in the format of the body." / "The expiry must be a date in the future."
|
||||
- 401: "You must be logged in to access this resource."
|
||||
- 403: "This action needs a real session." (session-only routes called with a key) / "Only the owner can do this." / "You must verify your account to access this resource."
|
||||
- 404: "Article not found" / "Image not found" / "Invite not found" / "API key not found"
|
||||
- 429: "Too many requests. Please try again later." A per-key limit also sends `Retry-After`.
|
||||
- 500: "Internal server error"
|
||||
- 409, only as examples under their endpoints: `POST /v1/user/invite` "This address already has an account."; `POST /v1/media/merge` "Some of the images to merge changed. Refresh and try again." There is no 409 or 422 row in the table.
|
||||
- 413 and 415 on `POST /v1/media/` keep their earlier plain captions; no real message is known.
|
||||
|
||||
## Request bodies
|
||||
- `POST /v1/article/`: `title` (string, required, 3 to 200 characters), `body` (string, required, max 10000).
|
||||
- `PATCH /v1/article/{id}`: `body` (string, required, max 10000).
|
||||
- `PATCH /v1/media/{id}` (rename): `filename` (string, required).
|
||||
- `POST /v1/media/merge`: `keep_id` (number, required, > 0), `merge_ids` (number[], required, at least 1, each > 0).
|
||||
- `POST /v1/media/`: multipart/form-data, 1 file field (shown as "multipart/form-data, 1 file field").
|
||||
- `PATCH /v1/user/me`: `display_name` (string, required, max 60 characters).
|
||||
- `POST /v1/user/invite`: `email` (string, required, valid email).
|
||||
- `POST /v1/system/update/restart`: optional body `{ "kind": "update" | "restart" }`.
|
||||
|
||||
## Component inventory and Nuxt UI v4
|
||||
- EndpointCard (extended): `UCollapsible` (trigger is a button with aria-expanded), `UBadge` (method, chips, status), `UTable` (body fields), `UTabs` (fetch, curl, Response), CodeBlock.
|
||||
- SectionIndex (new): custom `<nav>` of anchor buttons with `aria-current`; sticky, scroll-spy. Mobile: `USelectMenu` labelled "Jump to".
|
||||
- SessionOnlyGroup (new): `UAlert`-style info note plus list rows; no new colour.
|
||||
- ErrorTable: `UTable`. Info notes: existing note style (or `UAlert` variant `naked`).
|
||||
- API keys: `UTable`, `UBadge`, `UModal` with `UForm`/`UFormField`/`UInput` (type date), `UAlert` color warning, `UButton`, `useClipboard`.
|
||||
|
||||
## Assumptions to confirm
|
||||
Paths not in the brief: `/v1/settings`, `/v1/auth/api-key`, `/v1/system/update/*`, `POST /v1/auth/register|verify|logout`; body fields `content`, `keepId`, `mergeIds`, `displayName`, `name`; error body shape `{ "statusCode", "message" }`. Code samples use a simple keyword and string colouring.
|
||||
- Paths not in the brief: `/v1/settings`, `/v1/system/update/*`, `POST /v1/auth/register|verify|logout`.
|
||||
- [to confirm] The multipart field name on `POST /v1/media/` is written as `file` as a placeholder.
|
||||
- Response field names in the samples (for example `articlesUpdated`, `display_name` in the profile response) are illustrative.
|
||||
- Code samples use a simple keyword and string colouring.
|
||||
|
||||
## Tokens
|
||||
No new tokens. Foundations check: colours, radius (0) and spacing come from existing `--ui-*` and `--rc-*` values; every control has a 2 px primary focus ring; index, select and cards are keyboard operable. Open question: the board hard-codes a few pixel sizes, as the other screens do.
|
||||
Reference in new issue
Block a user