Skip to content

Commit 037483e

Browse files
authored
Merge pull request #29 from persys-dev/refactor/api-gateway-cleanup
refactor(gateway): dynamic gRPC-reflection routing, Postgres migration, deployment modes, and critical bug fixes
2 parents 8735011 + 9bfb24d commit 037483e

36 files changed

Lines changed: 2405 additions & 1929 deletions

persys-gateway/README.md

Lines changed: 78 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@
55
## Responsibilities
66

77
- Public HTTP ingress.
8-
- OAuth/session handling for GitHub login flow.
8+
- OAuth/session handling for GitHub login flow (managed deployments only — see Deployment Modes).
99
- GitHub webhook signature + replay validation.
10-
- Multi-cluster scheduler pool routing.
11-
- Proxy HTTP API calls to scheduler gRPC API.
12-
- Forward forgery-related actions to forgery gRPC API.
10+
- Multi-cluster scheduler pool routing, with automatic failover across scheduler replicas.
11+
- Dynamic HTTP-to-gRPC bridging for cluster control (workloads/nodes) and forgery (CI/CD), via gRPC reflection with a compiled-in fallback — see Dynamic API Surface.
1312
- Enforce mTLS for internal calls.
1413

1514
## Non-Responsibilities
@@ -18,40 +17,103 @@
1817
- Does not push images.
1918
- Does not perform scheduler-side build actions.
2019

20+
## Deployment Modes
21+
22+
Set via `deployment.mode` in `config.yaml` (or left unset):
23+
24+
- **`self-hosted`** (default) — no GitHub OAuth app required. `/auth/*` and
25+
`/github/*` routes aren't mounted at all. mTLS is the only trust
26+
boundary for cluster-control and forgery routes. No database is
27+
required — see Database below.
28+
- **`managed`** — GitHub OAuth mounts, cluster-control/forgery routes
29+
require a verified user JWT (or mTLS), and a database is required at
30+
startup (fails fast if `database.dsn` is empty).
31+
32+
`GET /health` reports the active `deployment_mode` and `database_enabled`
33+
so this is always visible at runtime, not just inferred from config.
34+
35+
## Database
36+
37+
Postgres, via `internal/store`**optional in self-hosted mode**. Leave
38+
`database.dsn` unset and the gateway runs with no database at all: the
39+
only things that ever touch it (OAuth login/session storage, webhook
40+
delivery audit trail) either aren't mounted in self-hosted mode or
41+
degrade gracefully to in-memory-only behavior. Managed mode requires it.
42+
43+
Schema is three tables (`users`, `oauth_sessions`, `webhook_events`),
44+
applied as idempotent `CREATE TABLE IF NOT EXISTS` on every startup —
45+
no separate migration command. See `internal/store/schema.sql` for what
46+
each table is for and what was deliberately *not* carried over from an
47+
earlier MongoDB-based version.
48+
2149
## Ports
2250

2351
From `config.yaml`:
2452
- mTLS API: `:8551`
2553
- public webhook API: `:8585`
54+
- debug/pprof: `:6060`
2655

2756
## Config
2857

2958
Primary config files:
3059
- `config.yaml`
3160
- `cluster.yaml` (scheduler clusters and routing)
61+
- `catalog.yaml` (optional — see Dynamic API Surface; absence is normal)
3262

3363
Important sections:
64+
- `deployment.mode` — see Deployment Modes
65+
- `app.jwt_secret` — required in managed mode, auto-generated with a
66+
startup warning in self-hosted (won't survive a restart unless set)
67+
- `database.dsn` — required in managed mode, optional in self-hosted
3468
- `tls`, `vault`
3569
- `scheduler` + `core_dns`
3670
- `webhook`
3771
- `forgery.grpc_addr`, `forgery.grpc_server_name`
3872

73+
Key environment variable overrides (see `config/config.go` for the full
74+
list): `PERSYS_GATEWAY_CONFIG`, `PERSYS_GATEWAY_JWT_SECRET`,
75+
`PERSYS_GATEWAY_POSTGRES_DSN`, `PERSYS_GATEWAY_CATALOG`.
76+
77+
## Dynamic API Surface
78+
79+
Cluster-control (workloads/nodes) and forgery (CI/CD) routes are not
80+
hand-written per RPC. `internal/grpcbridge` discovers methods via gRPC
81+
reflection against the live backend, falling back to the compiled-in
82+
proto descriptor if the backend doesn't support reflection yet — so a
83+
new RPC on either backend is reachable with zero gateway code changes,
84+
and works against existing deployments unmodified either way.
85+
86+
The full, current list of stable paths is `internal/router/bindings.go`.
87+
Anything not given a stable alias there is still callable at the generic
88+
`/clusters/:cluster_id/rpc/<Service>/<Method>` path, and every method
89+
(aliased or not) is listed at runtime:
90+
91+
```
92+
GET /clusters/:cluster_id/rpc/_meta
93+
GET /clusters/:cluster_id/forgery/rpc/_meta
94+
```
95+
3996
## Key Routes
4097

4198
Public:
4299
- `POST /webhooks/github`
43100

44101
mTLS API:
102+
- `GET /health`
45103
- `GET /clusters`
46-
- `POST /workloads/schedule`
47-
- `GET /workloads`
48-
- `GET /nodes`
49-
- `GET /cluster/metrics`
50-
- `POST /forgery/projects/upsert`
51-
- `POST /forgery/builds/trigger`
52-
- `POST /forgery/webhooks/test`
53-
54-
Cluster-scoped variants are under `/clusters/:cluster_id/...`.
104+
- `GET /clusters/:cluster_id`
105+
- `POST /clusters/:cluster_id/workloads/schedule`
106+
- `GET /clusters/:cluster_id/workloads`
107+
- `GET /clusters/:cluster_id/nodes`
108+
- `GET /clusters/:cluster_id/cluster/metrics`
109+
- `POST /clusters/:cluster_id/forgery/projects/upsert`
110+
- `POST /clusters/:cluster_id/forgery/builds/trigger`
111+
- `POST /clusters/:cluster_id/forgery/webhooks/test`
112+
113+
Managed mode only:
114+
- `GET /auth/login`
115+
- `GET /auth/` (OAuth callback)
116+
- `GET /github/list/repos`
55117

56118
## Run
57119

@@ -66,3 +128,6 @@ go run ./cmd
66128
cd persys-gateway
67129
go build ./cmd
68130
```
131+
132+
After pulling dependency changes (e.g. the Postgres migration), run
133+
`go mod tidy` once to settle `go.sum`.

0 commit comments

Comments
 (0)