Strip API Surface
Strip API Surface
Strip is a Fiber HTTP server that renders Templ pages and serves HTMX-style JSON fragments. It has no direct DB writes for domain entities — every business read or mutation is forwarded to sirloin over gRPC.
Topology
flowchart LR Browser -->|HTTPS| Strip[Strip Fiber<br/>:8080] Strip -->|Clerk SDK / cookie| Clerk[(Clerk)] Strip -->|gRPC| Sirloin[(sirloin StripService<br/>v5)] Strip -->|HTTPS| OpenRouter[(OpenRouter LLM)] Strip -->|HTTPS| Brisket[(brisket links)]See apps/strip/cmd/app/main.go startFiberServer (line 330+).
Middleware Stack (in order)
Registered in cmd/app/main.go:
requestid.New()— request ID for trace correlation.recover.New(EnableStackTrace: true)— panic recovery, returns 500.helmetMiddlewareForStage— security headers (CSP varies by stage).limiter.New(globalRateLimitMax) — IP-keyed global rate limit. Asset paths (/assets,/assets/...) are skipped viashouldSkipGlobalRateLimit.compress.New— gzip/brotli on dynamic responses.- Static file serving for
/assets.
A stricter authLimiter is layered onto /login, /auth/refresh, and /auth/clerk/callback.
Auth Surface
Auth is enforced by two middlewares (apps/strip/internal/app/middleware/):
AuthMiddleware.RequireAuth— verifies a Clerk session cookie or__sessiontoken; populatesc.Locals("userId" | "userEmail" | "sessionToken").AuthorizationMiddleware.RequirePermission(perm)— RBAC, fails with 403. HTMX requests get a JSON body +HX-Reswap: none, otherwise the forbidden Templ page.
Two dev-only bypass paths exist and emit SECURITY WARNING logs:
X-Auth-Bypass: <uuid>header (or?auth=<uuid>) matchingSTRIP_AUTH_BYPASS_UUID.Stage == developmentwithclerkService == nil.
Permission catalog (internal/app/authorization/authorization.go): view:dashboard, view:users, manage:credits, view:characters, create:character, update:character, delete:character, manage:nsfw, view:media, delete:media, view:audit_logs, view:dataset, view:examples, create:users, manage:roles, manage:admins.
Public Routes
| Method | Path | Handler | Notes |
|---|---|---|---|
| GET | /health | inline | liveness, no auth |
| GET | /login | HandleLogin | Clerk login page |
| POST | /login | HandleLoginPost | authLimiter |
| POST | /auth/refresh | HandleRefreshToken | authLimiter |
| POST | /auth/clerk/callback | HandleClerkCallback | authLimiter |
| GET | /sso-callback | HandleSSOCallback | |
| GET | / | createRootHandler | redirects per session state |
Protected Pages (RequireAuth)
| Path | Handler | Extra perm |
|---|---|---|
GET /dashboard | HandleDashboard | — |
GET /ask-strip | HandleAskStrip | view:audit_logs |
GET /users | HandleUsers | — |
GET /characters | HandleCharactersPage | — |
GET /dataset-gallery[/load-more] | HandleDatasetGallery | — |
GET /media[/load-more] | HandleListMedia | — |
GET /media/gallery[/load-more] | HandleMediaGallery | — |
GET /popular-examples[/load-more] | HandlePopularExamplesGallery | — |
GET /shop-vi[/load-more] | HandleShopVIListing | — |
GET /auditlogs | HandleAuditLogs | view:audit_logs |
GET /roles | HandleRolesPage | manage:roles |
DELETE /api/media/:id | HandleDeleteMedia | delete:media |
POST /logout | HandleLogout | — |
Protected JSON / HTMX API (/api/*, RequireAuth)
| Method | Path | Handler | Perm |
|---|---|---|---|
| GET | /api/auth/mcp-token | HandleMCPToken | — |
| GET | /api/users/search | HandleUserSearch | — |
| GET | /api/command-palette/search | HandleCommandPaletteSearch | — |
| GET | /api/search/preview | HandleSearchPreview | — |
| GET | /api/activity-feed | HandleActivityFeed | — |
| POST | /api/ask-strip/support-brief | HandleAskStripSupportBrief | view:audit_logs |
| POST | /api/ask-strip/chat | HandleAskStripChat | view:audit_logs |
| GET | /api/users/:id | HandleUserDetails | — |
| GET | /api/users/:id/panel | HandleUserPanel | — |
| POST | /api/users/:id/credits | HandleAddCredits | manage:credits |
| POST | /api/users/:id/characters | HandleCreateCharacter | create:character |
| POST | /api/users/create | HandleCreateClerkUser | create:users |
| GET | /api/characters/:id | HandleCharacterDetails | — |
| GET | /api/characters/:id/panel | HandleCharacterPanel | — |
| POST | /api/characters/:id/update | HandleUpdateCharacter | update:character |
| POST | /api/characters/:id/bypass-onboarding-checks | HandleBypassCharacterOnboardingChecks | update:character |
| DELETE | /api/characters/:id | HandleDeleteCharacter | delete:character |
| GET | /api/media/:id/panel | HandleMediaPanel | — |
| GET | /api/auditlogs/:id | HandleAuditLogDetails | view:audit_logs |
| GET | /api/roles | HandleListRoles | manage:roles |
| POST | /api/roles | HandleSetRole | manage:roles |
| DELETE | /api/roles/:userId | HandleDeleteRole | manage:roles |
Templ Pages
Templ files render every protected page above. They live under apps/strip/internal/app/strip/templates/ and are compiled by templ generate into *_templ.go siblings. The strip Fiber handlers call templates.<Page>(...).Render(ctx, c) rather than c.Render. See services/strip-datatable/ and services/strip-filters/ for the shared render primitives.
Downstream gRPC Calls
Strip embeds the generated client at apps/strip/internal/pkg/pb/sirloin/v5/. The proto contract is proto/sirloin/v5/strip.proto, service sirloin.v5.StripService. RPCs called by handlers include:
StripListUsers,StripUpdateUserStripListCharacters,StripCreateCharacter,StripUpdateCharacter,StripDeleteCharacter,StripBypassCharacterOnboardingChecksStripListMedia,StripFailMediaStripListPopularExamples,StripListPopularCategoriesStripListDatasetImagesStripLogAudit,StripListAuditLogs,StripGetAuditLogStripGetUserRole,StripListUserRoles,StripSetUserRole,StripDeleteUserRole(proto/sirloin/v5/strip.proto:33-36)StripCreateClerkUser(proto/sirloin/v5/strip.proto:39)StripFoxy360CreateThread,StripFoxy360SendMessage,StripFoxy360GetRun,StripFoxy360ListMessages,StripFoxy360ListArtifacts(proto/sirloin/v5/strip.proto:42-46)StripGetDashboardStats,StripGetSchema,StripRunReadonlyQuery(proto/sirloin/v5/strip.proto:28-30)StripListAvailableCharacters(proto/sirloin/v5/strip.proto:49). Credits surface as fields onStripListUsers/ character responses (credits_min,remaining_credits,standard_credits,full_access_credits) — no dedicated credits RPC.
The keepalive client is created in cmd/app/main.go (grpcKeepaliveTime=30s, grpcKeepaliveTimeout=10s) and reused for the process lifetime.