M4 Workstream B + M2 wsid registry: quota, OAuth, billing, admin, egress CLI, workspaces - #9
Merged
Merged
Conversation
OAuth org-gating (gm-o9t8.4.4.1): - AttachOrgGates setter on Router - oauthLogin handler calls OrgGate.Allow after fetchGitHubUser; non-members get 403 not_in_allowed_orgs before tenant provisioning - serve flags --oauth-github-allowed-orgs (csv) and --oauth-github-allowed-team (repeatable org:team); installs global gate keyed on empty tenant id - ServeConfig.OAuthGitHubAllowedOrgs/Teams - Test: TestOAuthLogin_OrgGateRefusesNonMember (httptest stub for /user, /user/orgs, /user/teams) Billing usage (gm-o9t8.4.1.1): - serve wires default billing.Aggregator via AttachUsageAggregator when --billing-meters-enable (default true) - ServeConfig.BillingMetersEnable
Wires a thin CLI surface over the existing egress.BuiltinTemplates
bundle + the `/api/v1/workspaces/{wsid}/egress-rules` HTTP surface.
- `gemba egress template list` (--json) reads BuiltinTemplates and
prints the available bundles + their network-default stance + hosts.
- `gemba egress template apply --workspace <wsid> --name <tpl>` fetches
the workspace's current rules, materializes the template's allowlist
into per-host rules with stable IDs (tpl-<name>-<host>), and POSTs
only the rules not already present. Re-applying is a no-op.
- `wide-open` emits a slog.Warn on apply documenting the operator's
acknowledgement that the workspace bypasses host filtering.
Tests use a stubbed egressAPIClient (no httptest needed). Story
admin endpoints (gm-o9t8.4.3.1) were already implemented in
internal/server/admin_console.go and tenants_admin.go on the Router;
this commit ships the egress story (gm-o9t8.4.3.2) and references the
already-landed admin surface in the closure note.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a per-tenant quota envelope keyed on subscription tier (free / solo / teams / enterprise) and the HTTP middleware that enforces it after WithTenant. Internals: - internal/quota: Tier + Limits model with LimitsForTier defaults, standalone goroutine-safe Bucket + BucketStore, and a read-only Counters projection (with a MemCounters test impl). - internal/server/middleware/quota.go: WithQuota composes after WithTenant. 429 + Retry-After on bucket exhaustion (emits quota.rate.limit audit event when an Auditor is wired), and 429 / 402 on the route-allowlisted concurrent-VM / monthly-minute / workspace ceilings. No-tenant requests bypass so upstream auth owns the 401. - internal/tenant: Tenant.Tier column with idempotent ALTER migration (information_schema probe + ADD COLUMN); MemStore + SQLStore both honor the new field. - internal/cli/serve.go: wires the tier middleware on /api after WithTenant when --quota-enforce=true (default). In-memory BucketStore today; Redis-backed store is the production follow-up. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 tasks done
…pnpm artifacts - internal/quota/quota_test.go: split `b.Allow() || b.Allow()` into two assignments so the second call actually executes (the || would have short-circuited on the first true return). - .gitignore: ignore /.pnpm-store/ (local pnpm cache) and testing/e2e/package-lock.json (this repo uses pnpm-lock.yaml). - Remove the two files that slipped in via an earlier `git add -A`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 tasks done
Add internal/workspaces package providing a Registry contract with two implementations: SQLStore (Dolt-backed, self-migrating) and MemStore (in-memory). Both share a conformance suite that pins Resolve/List/Create/Delete semantics, the (tenant_id, slug) uniqueness invariant, and cross-tenant slug collisions (t-A:foo vs t-B:foo resolve independently). Router gains AttachWorkspaceRegistry; the workspaceStatus handler prefers registry resolution and falls back to the legacy config.ListAllProjects basename match when the registry is unset or ErrNotFound, preserving M1 single-user behaviour. cmd/gemba serve wires the registry: SQLStore when --multi-tenant is on and a Dolt *sql.DB is available, otherwise MemStore. On first boot (controlled by --workspaces-bootstrap, default true) the server scans --workspaces-root and inserts a default-tenant row for every existing project dir. New `gemba workspace list|create|delete` subcommand operates against the same registry either via a direct Dolt SQL URL or an in-memory fallback for dry runs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Six stories landed under M4 productization (`gm-o9t8.4.`) and M2 federation (`gm-o9t8.2.`). All beads created, claimed, and closed.
gm-o9t8.4.2.1 — Tier-aware quota + rate-limit middleware
gm-o9t8.4.4.1 — GitHub OAuth org/team gating
gm-o9t8.4.1.1 — Billing usage counters + `/api/v1/tenants/:tid/usage`
gm-o9t8.4.3.1 — Operator admin endpoints
gm-o9t8.4.3.2 — Egress policy templates (CLI)
gm-o9t8.2.4 — wsid registry for multi-tenant resolution
Test plan
Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com