Sirloin API
The contract surface of sirloin. For service overview see Sirloin. For generated proto reference see proto-api.
Surface Map
Sirloin exposes four gRPC services and a small set of HTTP endpoints (health, webhooks, MCP). The single Go process listens on three ports:
| Port | Purpose | Source |
|---|---|---|
50051 | gRPC + gRPC-Web (h2c) | apps/sirloin/cmd/app/main.go (grpcHTTPServer) |
8087 | Webhook intake (HTTP) | apps/sirloin/cmd/app/main.go (webhookHTTPServer) |
8086 | MCP / Foxy360 (HTTP) | apps/sirloin/cmd/app/main.go (mcpHTTPServer) |
Defaults: container ports per docker-compose.yml (sirloin service).
Default SIRLOIN_PORT=:50051 per apps/sirloin/internal/app/config/config.go.
gRPC Services
Proto contracts live under proto/sirloin/v5/. Generated stubs are checked
into apps/sirloin/internal/pkg/pb/. RPC list below is summarised; for full
request/response shapes refer to the proto files and the generated docs at
proto-api.
SirloinService (proto/sirloin/v5/sirloin.proto)
End-user surface: characters, media, profile, KYC. Consumed by brisket over gRPC-Web. Selected RPCs (28 total):
CreateCharacter,UpdateCharacter,ListCharacters,DeleteCharacterGetCharacterReferenceImageUploadURL,GetCharacterReferenceDatasetUploadURLsVerifyCharacterReferenceDatasetImage,DeleteCharacterReferenceDatasetImageUpdateCharacterReferenceDataset,TriggerCharacterReferenceImageUploadedGenerateMedia,ListMedia,ToggleMediaFavorite,ToggleMediaArchived,SetMediaDownloaded,ListMediaTags,ListMediaExamplesGetUserProfile,UpdateUserProfile,RequestWelcomePics,SubmitFeedbackGetInstagramProfile,StartKYCVerification
BillingService (proto/sirloin/v5/billing.proto)
Billing surface: subscriptions, payments, products, coupons. Consumed by brisket and strip. Selected RPCs:
GetCurrentUsage,ListProducts,GetWorkflowPricingCreatePrimerCheckout,SubmitPaidInvoice,GetPayment,GetTransactionsGetSubscriptionDetails,CancelSubscription,ReactivateSubscription,CancelScheduledDowngrade,ProvideCancellationBenefitRetryDunningPayment,ValidateCoupon,SetReferralCodeGetPaymentMethods,AddPaymentMethod,DeletePaymentMethod,SetPrimaryPaymentMethod,CreateVaultingSessionUpdateBillingAddress,UpdateNextBillingDateForTesting(test-only)
Behaviour notes (deferred activation, polling, invariants) are described
in apps/sirloin/internal/app/services/billing/BILLING.md and the
billing runbook.
StripService (proto/sirloin/v5/strip.proto)
Admin surface consumed exclusively by strip (SSR admin). Auth via short-lived admin Clerk token (see auth-model). Selected RPCs:
StripListUsers,StripUpdateUserStripListCharacters,StripCreateCharacter,StripUpdateCharacter,StripDeleteCharacter,StripBypassCharacterOnboardingChecksStripListMedia,StripFailMedia,StripListDatasetImagesStripListPopularExamples,StripListPopularCategoriesStripLogAudit,StripListAuditLogs,StripGetAuditLog
FlankStorageService (proto/sirloin/v5/flank.proto) — legacy / being retired
Under T-Bone the workflow engine and storage moved into brain, which now owns workflows, subworkflows, adapters, secrets, and executions over an HTTP API. Flank is now only the visual workflow editor and reads/writes brain directly. This sirloin-hosted persistence surface is superseded.
TODO(@law): remove theFlankStorageService(and theFlankMCProute below) once no flow depends on it.
Legacy persistence surface for flank workflows, adapters, secrets, executions.
Authenticated by SIRLOIN_FLANK_SERVICE_TOKEN. Source:
apps/sirloin/internal/app/services/flank/. RPC families:
- Workflows:
FlankCreateWorkflow,FlankUpdateWorkflow,FlankGetWorkflow,FlankListWorkflows,FlankDeleteWorkflow,FlankPublishWorkflow - Adapters:
FlankCreateAdapter…FlankDeleteAdapter - Secrets:
FlankCreateSecret…FlankResolveSecrets - Executions:
FlankCreateExecution,FlankUpdateExecution,FlankGetExecution,FlankListExecutions
gRPC Health
grpc.health.v1.Health implemented in
apps/sirloin/internal/app/services/health.go. Used by the container
healthcheck (/bin/grpc_health_probe -addr=:50051).
REST Endpoints
Sirloin’s HTTP surface is intentionally narrow. Routes registered in
apps/sirloin/cmd/app/main.go against webhookMux, grpcHTTPMux, and
mcpMux.
| Method | Path | Server | Auth | Source |
|---|---|---|---|---|
| GET | /health | gRPC HTTP (50051) | none | internal/app/services/health.go |
| POST | /webhooks/chargebee/events | webhooks (8087) | HTTP Basic (SIRLOIN_CHARGEBEE_WEBHOOK_USERNAME / _PASSWORD) | internal/app/services/billing/webhooks/chargebeewebhook.go |
| POST | /webhooks/primer/disputes | webhooks (8087) | HMAC over SIRLOIN_PRIMER_WEBHOOK_SECRET | internal/app/services/billing/disputes/primerwebhook.go |
| POST | /webhooks/primer/payments | webhooks (8087) | HMAC over SIRLOIN_PRIMER_WEBHOOK_SECRET | internal/app/services/billing/webhooks/ (NewPrimerPaymentsWebhookHandler) |
| POST | /webhooks/ondato/verification-status | webhooks (8087) | shared secret SIRLOIN_ONDATO_WEBHOOK_SECRET | internal/app/services/characters/ondato_webhook.go |
| ANY | ${SIRLOIN_FOXY360_BASE_PATH}/* | MCP (8086) | Clerk (SIRLOIN_FOXY360_CLERK_API_KEY) via OAuth proxy | internal/app/foxy360/, internal/app/mcpoauth/ |
| ANY | ${FlankMCPBasePath}/* | MCP (8086) | flank service token | internal/app/flankmcp/ — legacy / being retired (workflow tooling moved to brain) |
grpcHTTPMux falls back to a 404 for everything except /health and the
gRPC + gRPC-Web protocol routes (apps/sirloin/cmd/app/main.go).
Webhooks Received
Chargebee Events
- Path:
POST /webhooks/chargebee/eventson port8087 - Auth: HTTP Basic with
SIRLOIN_CHARGEBEE_WEBHOOK_USERNAME/SIRLOIN_CHARGEBEE_WEBHOOK_PASSWORD. Missing creds → all webhooks rejected (config.gowarns at startup). - Payload: Chargebee event JSON (
event_type,content). - Behaviour: webhook is a fallback; sirloin’s own poller (every 15s, see
internal/app/services/billing/events/poller.go) is the authoritative ingest path.
Primer Disputes
- Path:
POST /webhooks/primer/disputeson port8087 - Auth: HMAC verified with
SIRLOIN_PRIMER_WEBHOOK_SECRET. 3-minute clock skew window (primer.WebhookSignedAtWithinSkew). - Body limit: 1 MiB (
maxPrimerWebhookBodyBytes).
Primer Payments
- Path:
POST /webhooks/primer/paymentson port8087 - Auth: same HMAC scheme as disputes.
- Behaviour: feeds the unified payment processor
(
internal/app/services/billing/payments/processor.go).
Ondato KYC
- Path:
POST /webhooks/ondato/verification-statuson port8087 - Auth: shared secret
SIRLOIN_ONDATO_WEBHOOK_SECRET.
Examples
# health probecurl -fsS http://localhost:50051/health
# gRPC reflection (dev only — sirloin docker-compose ships grpcui on :8821 too)grpcurl -plaintext localhost:50051 listgrpcurl -plaintext localhost:50051 sirloin.v5.BillingService/ListProductsVersioning
Proto package is pinned at sirloin.v5. Backwards-incompatible changes
require a new package version; field deprecation follows
documentation standard and
auth-model for auth changes. TODO(@zen): no
formal deprecation policy doc exists yet — confirm or add ADR.
TODO(@zen)
- TODO(@zen): is there a documented
sirloin.v5deprecation policy beyond proto file conventions? - Foxy360 MCP routes are internal-only. The
${SIRLOIN_FOXY360_BASE_PATH}/*surface is gated by Clerk verification (SIRLOIN_FOXY360_CLERK_API_KEY) through an OAuth proxy and exposes admin/analytics tooling. Source:apps/sirloin/internal/app/foxy360/server.go:1and registration inapps/sirloin/cmd/app/main.go(mcpHTTPServer). - Primer payments webhook uses the same 1 MiB body cap as disputes.
maxPrimerPaymentBodyBytes = 1 * 1024 * 1024inapps/sirloin/internal/app/services/billing/webhooks/primerpaymentwebhook.go:22, matchingmaxPrimerWebhookBodyBytesinapps/sirloin/internal/app/services/billing/disputes/primerwebhook.go:26.