Skip to content

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.

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+).

Registered in cmd/app/main.go:

  1. requestid.New() — request ID for trace correlation.
  2. recover.New(EnableStackTrace: true) — panic recovery, returns 500.
  3. helmetMiddlewareForStage — security headers (CSP varies by stage).
  4. limiter.New (globalRateLimitMax) — IP-keyed global rate limit. Asset paths (/assets, /assets/...) are skipped via shouldSkipGlobalRateLimit.
  5. compress.New — gzip/brotli on dynamic responses.
  6. Static file serving for /assets.

A stricter authLimiter is layered onto /login, /auth/refresh, and /auth/clerk/callback.

Auth is enforced by two middlewares (apps/strip/internal/app/middleware/):

  • AuthMiddleware.RequireAuth — verifies a Clerk session cookie or __session token; populates c.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>) matching STRIP_AUTH_BYPASS_UUID.
  • Stage == development with clerkService == nil.

Permission catalog (internal/app/authorization/authorization.go): view:dashboard, view:users, manage:credits, view:characters, create:character, update:character, delete:character, manage:nsfw, manage:approved_celebrity, view:media, delete:media, view:audit_logs, view:dataset, view:examples, view:payments, create:users, manage:roles, manage:admins.

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
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 /payments HandlePayments view:payments
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)

Section titled “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 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.

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, StripUpdateUser
  • StripListCharacters, StripCreateCharacter, StripUpdateCharacter, StripDeleteCharacter, StripBypassCharacterOnboardingChecks
  • StripListMedia, StripFailMedia
  • StripListPopularExamples, StripListPopularCategories
  • StripListDatasetImages
  • StripLogAudit, StripListAuditLogs, StripGetAuditLog
  • StripGetUserRole, 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)
  • StripGetPaymentsDashboard (proto/sirloin/v5/strip.proto:47) — the aggregated renewal, cohort and decline series behind /payments
  • StripListAvailableCharacters (proto/sirloin/v5/strip.proto:49). Credits surface as fields on StripListUsers / 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.