fix(api): 删除未接通的 Access JWT 委托,外部面只认会话 cookie,admin 主机的 IP 判定只认安装指定的地址,文档与 OpenAPI 同步

This commit is contained in:
Lemon-miaow committed 2026-09-25 15:35:26 +08:00
1 parent a883c1fe07
commit 38288e1c60
15 files changed
+274 -382

No files matched your search

+103 -109
View File
@@ -26,10 +26,11 @@ info:
version: 4.1.0
description: |
Control plane for the Felis Minecraft orchestration platform. The same binary
exposes an internal face (service-token auth, for velocity / backend callbacks,
never Zero Trust) and an external face (Cloudflare Access JWT auth, for people
and the panel). Admin-tier external operations additionally require the admin
Access path. See `x-felis-face` / `x-felis-tier` on each operation.
exposes an internal face (per-caller service tokens, for velocity / backend
callbacks, never Zero Trust) and an external face (the felis_session cookie, for
people and the panel; Cloudflare Access, when present, is enforced at the edge).
Admin-tier external operations additionally require a staff session on the
operator console host. See `x-felis-face` / `x-felis-tier` on each operation.
Behaviour every operation shares, and so not repeated under each:
@@ -63,8 +64,9 @@ servers:
default: example.test
- url: https://api.{root_domain}
description: >-
External face. Cloudflare Access JWT auth on every /api/v1 route; admin-tier
routes additionally require the admin Access path.
External face. Session-cookie auth on every non-public /api/v1 route;
admin-tier routes additionally require a staff session on the operator
console host.
variables:
root_domain:
default: example.test
@@ -105,14 +107,6 @@ components:
callers it serves in x-felis-callers. A genuine token for a caller the
operation does not list is refused with 403 wrong_caller. `felis
rotate-token <caller>` replaces one.
accessJWT:
type: apiKey
in: header
name: Cf-Access-Jwt-Assertion
description: >-
Cloudflare Access JWT (external face). Admin-tier operations require the
token to have traversed the admin Access path; the handler additionally
asserts Principal.IsAdmin().
sessionCookie:
type: apiKey
in: cookie
@@ -122,8 +116,10 @@ components:
session doors — passkey login, email-OTP, bind code, and op-login
finish — HttpOnly+Secure+SameSite=Lax and host-only, so an op.console
session never reaches the player console. Only its sha-256 is
persisted. SessionAuth prefers this cookie and otherwise delegates to
accessJWT, so the two models coexist on one face.
persisted. It is the external face's only credential: Cloudflare
Access, when the install sits behind it, is enforced at the edge and
felis-api does not read the Access JWT. Admin-tier operations
additionally require a staff session on the operator console host.
responses:
NoContent:
@@ -785,14 +781,14 @@ paths:
operationId: createServer
summary: Create a server (admin).
description: >-
Requires the admin Access path; the image must be whitelisted. An image in the
Requires a staff session on the operator console host; the image must be whitelisted. An image in the
platform registry is stored pinned to the digest its tag names at creation
(name:tag@sha256:…), so a later push over the tag never moves the server;
400 image_not_in_registry when the registry lacks the tag, 503
registry_unavailable when it cannot be asked.
x-felis-face: [external]
x-felis-tier: admin
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
requestBody:
required: true
content:
@@ -1444,7 +1440,7 @@ paths:
summary: Wake your own server.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: name, in: path, required: true, schema: { type: string } }
responses:
@@ -1482,7 +1478,7 @@ paths:
summary: Stop your own server.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: name, in: path, required: true, schema: { type: string } }
responses:
@@ -1510,7 +1506,7 @@ paths:
summary: Claim an unowned server for your linked account.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: name, in: path, required: true, schema: { type: string } }
responses:
@@ -1552,7 +1548,7 @@ paths:
description: The RCON password is never accepted or returned (spec §286).
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: name, in: path, required: true, schema: { type: string } }
requestBody:
@@ -1598,7 +1594,7 @@ paths:
summary: Stream the running pod's log over SSE (spec §8 read, §262). Owner/admin only.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: name, in: path, required: true, schema: { type: string } }
- name: Last-Event-ID
@@ -1637,7 +1633,7 @@ paths:
(spec §286).
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: name, in: path, required: true, schema: { type: string } }
responses:
@@ -1676,7 +1672,7 @@ paths:
(spec §286).
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: name, in: path, required: true, schema: { type: string } }
requestBody:
@@ -1720,7 +1716,7 @@ paths:
The RCON password is never accepted or returned (spec §286).
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: name, in: path, required: true, schema: { type: string } }
responses:
@@ -1762,7 +1758,7 @@ paths:
(spec §286).
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: name, in: path, required: true, schema: { type: string } }
responses:
@@ -1800,7 +1796,7 @@ paths:
records intent). The RCON password is never accepted or returned (§286).
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: name, in: path, required: true, schema: { type: string } }
requestBody:
@@ -1844,7 +1840,7 @@ paths:
never accepted or returned (spec §286).
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: name, in: path, required: true, schema: { type: string } }
requestBody:
@@ -1897,7 +1893,7 @@ paths:
(spec §286).
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: name, in: path, required: true, schema: { type: string } }
requestBody:
@@ -1943,7 +1939,7 @@ paths:
password is never accepted or returned (spec §286).
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: name, in: path, required: true, schema: { type: string } }
requestBody:
@@ -1989,7 +1985,7 @@ paths:
is echoed back for anything the parser cannot represent.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: name, in: path, required: true, schema: { type: string } }
- { name: player, in: path, required: true, schema: { type: string } }
@@ -2043,7 +2039,7 @@ paths:
displayName, phase, ready, playersOnline and playersMax.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: name, in: path, required: true, schema: { type: string } }
responses:
@@ -2870,14 +2866,13 @@ paths:
summary: The caller's own identity and tier (drives panel navigation).
description: >-
Returns the authenticated principal's user id, email, role and the
server-computed is_admin (Principal.IsAdmin(): role admin reached via the
admin Access path). The panel reads this once at boot to decide which
server-computed is_admin (Principal.IsAdmin(): role admin reached on the operator console host). The panel reads this once at boot to decide which
surfaces to render. It is UX truth, not a security control — admin routes
are independently gated server-side, so a hidden nav item never widens
access.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
responses:
'200':
description: The caller's identity.
@@ -2897,11 +2892,11 @@ paths:
type: boolean
description: >-
True only when role is admin or owner AND the request arrived
via the admin Access path (Principal.IsAdmin()).
on the operator console host (Principal.IsAdmin()).
is_owner:
type: boolean
description: >-
True only for the Owner principal on the admin Access path
True only for the Owner principal on the operator console host
(Principal.IsOwner()); gates owner-only panel surfaces.
email_verified:
type: boolean
@@ -2918,7 +2913,7 @@ paths:
summary: List the servers the caller owns or may claim.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
responses:
'200':
description: The caller's server list.
@@ -2948,7 +2943,7 @@ paths:
no behavior yet.
x-felis-face: [external]
x-felis-tier: admin
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
responses:
'200':
description: The current maintenance window (both ends null when unset).
@@ -2974,7 +2969,7 @@ paths:
component degrades to notify.
x-felis-face: [external]
x-felis-tier: admin
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
requestBody:
required: true
content:
@@ -3007,7 +3002,7 @@ paths:
max_age_seconds. Read-only: backups run on the host, never through the API.
x-felis-face: [external]
x-felis-tier: admin
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
responses:
'200':
description: The newest recorded backup and whether it is stale.
@@ -3034,7 +3029,7 @@ paths:
for display — best-effort, so a Postgres blip degrades to owner-less rows.
x-felis-face: [external]
x-felis-tier: admin
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
responses:
'200':
description: Every server's status projection (fleet-wide), each with its owner.
@@ -3059,7 +3054,7 @@ paths:
summary: List world backups (admin sees all; a user sees only worlds they formerly owned).
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
responses:
'200':
description: Visible backups.
@@ -3091,7 +3086,7 @@ paths:
Pass safety_snapshot false to restore straight away.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: name, in: path, required: true, schema: { type: string } }
requestBody:
@@ -3154,7 +3149,7 @@ paths:
asynchronously as a Job, so success is 202 (backing_up).
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: name, in: path, required: true, schema: { type: string } }
responses:
@@ -3198,7 +3193,7 @@ paths:
"running" | "succeeded" | "failed".
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: name, in: path, required: true, schema: { type: string } }
responses:
@@ -3267,7 +3262,7 @@ paths:
Listings are capped; truncated reports that the cap was hit.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: name, in: path, required: true, schema: { type: string } }
- name: path
@@ -3336,7 +3331,7 @@ paths:
subsequent save destroy the other half.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: name, in: path, required: true, schema: { type: string } }
- name: path
@@ -3408,7 +3403,7 @@ paths:
otherwise 409 file_changed. Audited as file.write.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: name, in: path, required: true, schema: { type: string } }
- name: path
@@ -3492,7 +3487,7 @@ paths:
first. Every route under /users gates on the admin Zero-Trust path.
x-felis-face: [external]
x-felis-tier: owner
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: query, in: query, required: false, schema: { type: string }, description: Substring match on username or email }
- { name: role, in: query, required: false, schema: { type: string, enum: [admin, user] } }
@@ -3522,7 +3517,7 @@ paths:
summary: Create a user (admin only).
x-felis-face: [external]
x-felis-tier: owner
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
requestBody:
required: true
content:
@@ -3562,7 +3557,7 @@ paths:
summary: Get user detail (admin only).
x-felis-face: [external]
x-felis-tier: owner
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
responses:
@@ -3583,7 +3578,7 @@ paths:
summary: Edit a user (admin only, cannot patch self).
x-felis-face: [external]
x-felis-tier: owner
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
requestBody:
@@ -3625,7 +3620,7 @@ paths:
summary: Soft-delete a user — releases servers, revokes sessions (admin only, cannot delete self).
x-felis-face: [external]
x-felis-tier: owner
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
responses:
@@ -3659,7 +3654,7 @@ paths:
immediate. Re-enabling simply clears the flag.
x-felis-face: [external]
x-felis-tier: owner
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
requestBody:
@@ -3700,7 +3695,7 @@ paths:
summary: Get a user's quotas (admin only).
x-felis-face: [external]
x-felis-tier: owner
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
responses:
@@ -3719,7 +3714,7 @@ paths:
summary: Set a user's quotas (admin only).
x-felis-face: [external]
x-felis-tier: owner
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
requestBody:
@@ -3753,7 +3748,7 @@ paths:
summary: List a user's live sessions (admin only).
x-felis-face: [external]
x-felis-tier: owner
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
responses:
@@ -3778,7 +3773,7 @@ paths:
summary: Revoke every live session of a user (admin only).
x-felis-face: [external]
x-felis-tier: owner
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
responses:
@@ -3803,7 +3798,7 @@ paths:
summary: Revoke a single session of a user (admin only).
x-felis-face: [external]
x-felis-tier: owner
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
- { name: hash, in: path, required: true, schema: { type: string } }
@@ -3844,7 +3839,7 @@ paths:
no-op, not a 404.
x-felis-face: [external]
x-felis-tier: owner
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
responses:
@@ -3875,7 +3870,7 @@ paths:
protection.
x-felis-face: [external]
x-felis-tier: owner
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
requestBody:
@@ -3919,7 +3914,7 @@ paths:
summary: Remove a single Minecraft UUID binding from a user (admin only).
x-felis-face: [external]
x-felis-tier: owner
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
- { name: mc_uuid, in: path, required: true, schema: { type: string, format: uuid } }
@@ -3951,7 +3946,7 @@ paths:
summary: Report account-link status and in-game instructions (web side, spec §10).
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
responses:
'200':
description: Current link status.
@@ -3973,7 +3968,7 @@ paths:
summary: Consume an in-game link code and bind the account.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
requestBody:
required: true
content:
@@ -4024,7 +4019,7 @@ paths:
session must have reauthed within 5 minutes (403 reauth_required).
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
requestBody:
required: true
content:
@@ -4085,7 +4080,7 @@ paths:
consumed, or mismatched code is a 400.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
requestBody:
required: true
content:
@@ -4135,7 +4130,7 @@ paths:
must have reauthed within 5 minutes (403 reauth_required).
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
requestBody:
required: true
content:
@@ -4180,7 +4175,7 @@ paths:
instance.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
responses:
'200':
description: "WebAuthn credential-creation options (the publicKey document)."
@@ -4214,7 +4209,7 @@ paths:
configured.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
requestBody:
required: true
content:
@@ -4262,7 +4257,7 @@ paths:
not need the WebAuthn verifier, so it succeeds even where begin/finish report 503.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
responses:
'200':
description: The caller's bound passkeys.
@@ -4294,7 +4289,7 @@ paths:
(403 reauth_required).
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- name: id
in: path
@@ -4333,7 +4328,7 @@ paths:
op-login or a passkey).
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
responses:
'200':
description: Where the caller stands.
@@ -4361,7 +4356,7 @@ paths:
bound to a fresh reauth-purpose challenge.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
responses:
'200':
description: WebAuthn assertion request options (PublicKeyCredentialRequestOptions) for navigator.credentials.get.
@@ -4388,7 +4383,7 @@ paths:
clone check (a cloned authenticator is 400 passkey_login_invalid).
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
requestBody:
required: true
content:
@@ -4423,7 +4418,7 @@ paths:
signing in again (403 staff_reauth).
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
responses:
'202':
description: Code minted and dispatched.
@@ -4471,7 +4466,7 @@ paths:
summary: Redeem the reauth code and mark this session reauthed for 5 minutes.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
requestBody:
required: true
content:
@@ -4515,12 +4510,11 @@ paths:
operationId: listMySessions
summary: List the caller's own live sessions, marking the one this request came in on.
description: >
Every device signed in to the caller's account, most recently seen first. A
caller signed in through Cloudflare Access has no session of its own, so no
entry is marked current.
Every device signed in to the caller's account, most recently seen first,
with the one this request came in on marked current.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
responses:
'200':
description: The caller's live sessions.
@@ -4547,7 +4541,7 @@ paths:
a sign-out; the cookie is cleared and signed_out is true.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: hash, in: path, required: true, schema: { type: string } }
responses:
@@ -4578,7 +4572,7 @@ paths:
summary: Sign out every session of the caller except the one making this request.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
responses:
'200':
description: Other sessions revoked.
@@ -4607,7 +4601,7 @@ paths:
caller has no live migration.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
responses:
'200':
description: The caller's live migration, or active:false.
@@ -4643,7 +4637,7 @@ paths:
of band and never returned; requires a verified email on the account.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
responses:
'202':
description: Confirmation code minted and dispatched.
@@ -4695,7 +4689,7 @@ paths:
unknown, expired, consumed, or mismatched code is a 400 invalid_code.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
requestBody:
required: true
content:
@@ -4753,7 +4747,7 @@ paths:
the login door does, runs the clone-signal (sign-count) check before confirming.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
responses:
'200':
description: WebAuthn assertion request options (PublicKeyCredentialRequestOptions) for navigator.credentials.get.
@@ -4787,7 +4781,7 @@ paths:
success the migration advances to confirmed with confirm_factor passkey.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
requestBody:
required: true
content:
@@ -4836,7 +4830,7 @@ paths:
must exist and be neither disabled nor soft-deleted, and cannot be the source.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
requestBody:
required: true
content:
@@ -4890,7 +4884,7 @@ paths:
keeps its own in-game identity and credentials; only server ownership moves.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
requestBody:
required: true
content:
@@ -4929,7 +4923,7 @@ paths:
summary: Submit a modpack for admin review (user side; user-directed lane over §16). Starts no build.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
requestBody:
required: true
content:
@@ -4970,7 +4964,7 @@ paths:
summary: List the caller's own modpack submissions with each linked build's outcome (user-directed lane over §16).
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
responses:
'200':
description: >-
@@ -5009,7 +5003,7 @@ paths:
store has no implemented upload transport.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
requestBody:
@@ -5056,7 +5050,7 @@ paths:
this endpoint cannot probe or clear another user's uploads.
x-felis-face: [external]
x-felis-tier: app
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
responses:
@@ -5085,7 +5079,7 @@ paths:
summary: Mutate a server spec (admin). Storage is immutable.
x-felis-face: [external]
x-felis-tier: admin
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: name, in: path, required: true, schema: { type: string } }
requestBody:
@@ -5163,7 +5157,7 @@ paths:
demand) and leave out the Dockerfile, which GET /images/build/{id} returns.
x-felis-face: [external]
x-felis-tier: admin
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: query, in: query, required: false, schema: { type: string }, description: 'Build id or status (exact), or part of the image ref; case-insensitive' }
- { name: limit, in: query, required: false, schema: { type: integer, default: 20, maximum: 100 } }
@@ -5193,7 +5187,7 @@ paths:
summary: Submit an image build (admin). A build is build-time RCE against the cluster.
x-felis-face: [external]
x-felis-tier: admin
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
requestBody:
required: true
content:
@@ -5242,7 +5236,7 @@ paths:
summary: Get one build's status (admin).
x-felis-face: [external]
x-felis-tier: admin
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
responses:
@@ -5267,7 +5261,7 @@ paths:
summary: Stream a build's Job log over SSE (admin, spec §16 / §416).
x-felis-face: [external]
x-felis-tier: admin
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
- name: Last-Event-ID
@@ -5299,7 +5293,7 @@ paths:
summary: Cancel a running build (admin).
x-felis-face: [external]
x-felis-tier: admin
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
responses:
@@ -5329,7 +5323,7 @@ paths:
summary: List whitelisted images (admin).
x-felis-face: [external]
x-felis-tier: admin
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
responses:
'200':
description: The image whitelist.
@@ -5354,7 +5348,7 @@ paths:
summary: Whitelist an externally-built image by reference (admin).
x-felis-face: [external]
x-felis-tier: admin
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
requestBody:
required: true
content:
@@ -5384,7 +5378,7 @@ paths:
summary: Remove an image from the whitelist by reference (admin).
x-felis-face: [external]
x-felis-tier: admin
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: ref, in: query, required: true, schema: { type: string } }
responses:
@@ -5408,7 +5402,7 @@ paths:
summary: The admin review queue — every user's modpack submissions (admin; user-directed lane over §16).
x-felis-face: [external]
x-felis-tier: admin
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
responses:
'200':
description: All submissions, newest first.
@@ -5437,7 +5431,7 @@ paths:
Approval is layered in front of the scan, never instead of it.
x-felis-face: [external]
x-felis-tier: admin
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
responses:
@@ -5475,7 +5469,7 @@ paths:
deployment's context store has no implemented transport.
x-felis-face: [external]
x-felis-tier: admin
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
responses:
@@ -5500,7 +5494,7 @@ paths:
summary: Reject a submission with a required reason (admin; user-directed lane over §16). Starts no build.
x-felis-face: [external]
x-felis-tier: admin
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
requestBody:
@@ -5548,7 +5542,7 @@ paths:
fetch; the admin has explicitly chosen to retire the artifact.
x-felis-face: [external]
x-felis-tier: admin
security: [{ accessJWT: [] }]
security: [{ sessionCookie: [] }]
parameters:
- { name: id, in: path, required: true, schema: { type: string } }
responses: