diff --git a/docs/README.md b/docs/README.md index 18ebb2f2..4aaace29 100644 --- a/docs/README.md +++ b/docs/README.md @@ -27,6 +27,7 @@ Feature/ops docs (already present): - `docs/webhook.md`: Discord webhook events/payload. - `docs/diffing.md`: version-to-version diff UI spec. - `docs/manual-testing.md`: CLI smoke scripts. +- `docs/slug-routing.md`: skill/plugin slug redirects + package URL contract. Docs tooling: diff --git a/docs/http-api.md b/docs/http-api.md index 5a6502c5..b1ceba32 100644 --- a/docs/http-api.md +++ b/docs/http-api.md @@ -17,11 +17,9 @@ OpenAPI: `/api/v1/openapi.json`. Third-party directories may use the public read endpoints to list or search ClawHub skills. Please cache results, honor `429`/`Retry-After`, link users back to the canonical ClawHub listing (`https://clawhub.ai//`), and avoid implying ClawHub endorsement of the third-party site. Do not attempt to mirror hidden, private, or moderation-blocked content outside the public API surface. -Web slug shortcuts resolve across registry families. Root paths matching -official OpenClaw extension slugs, such as `/codex` or `/anthropic`, redirect to -the mapped OpenClaw plugin package. Other root paths may redirect to a canonical -skill page. Owner-qualified OpenClaw extension paths such as `/openclaw/codex` -also redirect to the plugin listing. +Web slug shortcuts resolve across registry families. See `docs/slug-routing.md` +for the route precedence, collision policy, and official OpenClaw extension +alias contract. ## Rate limits diff --git a/docs/slug-routing.md b/docs/slug-routing.md new file mode 100644 index 00000000..6394b40d --- /dev/null +++ b/docs/slug-routing.md @@ -0,0 +1,124 @@ +--- +summary: "Internal routing contract for skill slugs, OpenClaw extension aliases, and plugin package URLs." +read_when: + - Changing web slug redirects + - Adding or renaming official OpenClaw extensions + - Debugging skill/plugin URL collisions + - Updating package or skill detail routes +--- + +# Slug routing + +ClawHub has two extension-like registries today: + +- Skills, backed by the skill registry and canonical owner/slug pages. +- Plugins, backed by package names and canonical package pages. + +The web router deliberately makes both feel close, but it does not collapse the +two namespaces into one database object. The route resolver decides whether a +request is a skill slug, an official OpenClaw plugin alias, or a package route. + +## Canonical URLs + +Skills: + +- Canonical page: `//` +- API detail: `/api/v1/skills/` + +Plugins: + +- Canonical page: `/plugins/@scope/name` +- Encoded compatibility page: `/plugins/%40scope%2Fname` +- Security page: `/plugins/@scope/name/security/` +- Encoded security compatibility page: `/plugins/%40scope%2Fname/security/` + +Encoded compatibility routes are npm-style package-name routes. They redirect +with `308` to the readable scoped route so the address bar shows +`/plugins/@openclaw/codex`, not `/plugins/%40openclaw%2Fcodex`. + +## Official OpenClaw aliases + +Official OpenClaw extension aliases live in +`src/lib/openClawExtensionSlugs.ts`. Each alias maps to one package name: + +```ts +codex -> @openclaw/codex +anthropic -> @openclaw/anthropic-provider +kimi -> @openclaw/kimi-provider +kimi-coding -> @openclaw/kimi-provider +``` + +These aliases come from the OpenClaw extension inventory. Include the folder +slug, package slug, and any user-facing plugin alias when they differ. + +For every official alias, these URLs redirect to the canonical plugin page: + +- `/` +- `/openclaw/` +- `/@openclaw/` + +Example: + +```text +/codex -> /plugins/@openclaw/codex +/openclaw/codex -> /plugins/@openclaw/codex +/@openclaw/codex -> /plugins/@openclaw/codex +``` + +## Route precedence + +The effective precedence is: + +1. Static app routes win first, such as `/search`, `/settings`, `/plugins`, and + `/api/...`. +2. A top-level path matching an official OpenClaw extension alias redirects to + that plugin package. +3. Any other top-level path may resolve through the skill registry and redirect + to `//`. +4. `/openclaw/` and `/@openclaw/` only resolve official OpenClaw + plugin aliases. +5. Other `/:owner/:slug` paths resolve as skills. +6. `/:owner/:slug` with an unsupported `@scope` owner returns not found instead + of accidentally resolving a skill by slug. +7. `/plugins/@scope/name` is the readable scoped plugin package route. +8. `/plugins/` probes package candidates in this order: official OpenClaw + alias package, `@openclaw/`, then the unscoped package name. + +This means official OpenClaw aliases are reserved before skills at the root. +That is intentional: `https://clawhub.ai/codex` must show the official OpenClaw +Codex plugin even if a skill named `codex` exists. + +## Collision policy + +Do not make every `/:owner/:slug` path a universal package route. Owners can +have skills and plugins, and skill slugs are already unique in the skill +registry. Package names have separate npm-like semantics. The only owner-style +plugin redirects currently reserved are for the official OpenClaw owner: + +- `/openclaw/` +- `/@openclaw/` + +Unknown top-level slugs still fall back to skill resolution. Unknown +`@scope/name` owner routes return not found unless a dedicated package route +handles them under `/plugins/...`. + +## Adding an official extension + +When OpenClaw ships a new extension: + +1. Add all expected aliases to `src/lib/openClawExtensionSlugs.ts`. +2. Keep every alias lowercase. +3. Map aliases to the npm package name, usually `@openclaw/`. +4. Add folder, package, and common short aliases when they differ. +5. Run the slug and package route tests. +6. Live-test the route matrix against production after deploy. + +The route tests should cover: + +- `/` redirects to `/plugins/@openclaw/`. +- `/openclaw/` redirects to `/plugins/@openclaw/`. +- `/@openclaw/` redirects to `/plugins/@openclaw/`. +- `/plugins/%40openclaw%2F` redirects to + `/plugins/@openclaw/`. +- `/plugins/@openclaw/` renders the plugin page. +- Security routes keep the same readable scoped URL behavior.