feat(gateway): phase7 public access layer (entitlements, rate limits, public list)

This commit is contained in:
Apple
2026-03-05 09:19:25 -08:00
parent e6e705a38b
commit 465669fc1d
5 changed files with 2187 additions and 26 deletions

View File

@@ -0,0 +1,106 @@
# Phase-7 Public Access Layer
## Scope
- Public discovery endpoint: `GET /v1/agents/public`
- Entitlements check in gateway before router call
- Rate limits in gateway for:
- `user_global`
- `user_agent`
- `group_agent`
## Data Model
Migration: `migrations/056_agent_access_policies.sql`
Tables:
- `agent_access_policies`
- `agent_allowlist`
## Gateway Env
- `GATEWAY_PUBLIC_ACCESS_ENABLED=true`
- `GATEWAY_ACCESS_POLICY_CACHE_TTL_SECONDS=60`
- `GATEWAY_ALLOWLIST_CACHE_TTL_SECONDS=30`
- `GATEWAY_ACCESS_DB_TIMEOUT_MS=40`
- `GATEWAY_ACCESS_DENY_COOLDOWN_SECONDS=30`
- `GATEWAY_RL_USER_GLOBAL_LIMIT=60`
- `GATEWAY_RL_USER_GLOBAL_WINDOW_SECONDS=300`
- `GATEWAY_RL_USER_AGENT_LIMIT=20`
- `GATEWAY_RL_USER_AGENT_WINDOW_SECONDS=300`
- `GATEWAY_RL_GROUP_AGENT_LIMIT=10`
- `GATEWAY_RL_GROUP_AGENT_WINDOW_SECONDS=300`
## Public Discovery
```bash
curl -sS http://127.0.0.1:9300/v1/agents/public | jq
```
Expected:
- `count` includes only `enabled && public_active` agents.
- planned/internal agents are excluded.
## Entitlements Operations
Add whitelist user:
```sql
INSERT INTO agent_allowlist(platform, platform_user_id, agent_id)
VALUES ('telegram', '123456789', 'helion')
ON CONFLICT (platform, platform_user_id, agent_id) DO NOTHING;
```
Require whitelist for an agent:
```sql
UPDATE agent_access_policies
SET requires_whitelist = TRUE, updated_at = now()
WHERE agent_id = 'helion';
```
Disable agent public access:
```sql
UPDATE agent_access_policies
SET enabled = FALSE, public_active = FALSE, updated_at = now()
WHERE agent_id = 'aistalk';
```
## Rate-Limit Policy Update
```sql
UPDATE agent_access_policies
SET
user_global_limit = 30,
user_global_window_seconds = 300,
user_agent_limit = 10,
user_agent_window_seconds = 300,
group_agent_limit = 5,
group_agent_window_seconds = 300,
updated_at = now()
WHERE agent_id = 'agromatrix';
```
## Fixed Smoke
1. Discovery:
```bash
curl -sS http://127.0.0.1:9300/v1/agents/public | jq '.count'
```
2. Whitelist deny:
- Set `requires_whitelist=true` for test agent.
- Replay webhook from user not in allowlist.
- Expected: deny ACK and event reason `access_whitelist_required`.
3. Whitelist allow:
- Insert user to `agent_allowlist`.
- Replay webhook.
- Expected: request continues to normal processing path.
4. Rate limit:
- Set low policy (`user_agent_limit=2`, window 60s).
- Send 3 quick webhooks from same user/agent.
- Expected: third request is `429`-style deny path and `reason=rate_limit_user_agent`.
5. Event invariant:
- `1 webhook -> 1 gateway event` remains true.
## PASS
- `/v1/agents/public` returns only public enabled agents.
- Entitlement decisions are deterministic (`allow|deny|rate_limited`).
- Metrics increment:
- `gateway_access_decisions_total`
- `gateway_rate_limited_total`
- No regression in webhook event finalize behavior.