feat(auth): gateway completeness, TenantId extractor, POST /auth/validate, Procfile#1129
feat(auth): gateway completeness, TenantId extractor, POST /auth/validate, Procfile#1129geoffjay wants to merge 2 commits intofeature/corefrom
Conversation
|
This change is part of the following stack: Change managed by git-spice. |
…actor, token validation
…date, Procfile
- Add memory (17008), communicate (17010), index (17012) to ProxyConfig::from_env()
and expand test_proxy_config_defaults / add test_proxy_config_new_service_defaults
- New agentd-common::tenant module: TenantId and OptionalTenantId axum extractors
that read X-Tenant-ID; AGENTD_REQUIRE_TENANT=true enables strict 400 rejection
- Add POST /auth/validate endpoint to core service: validates bearer token and
returns { valid, user_id, organization_id } for WebSocket upgrade checks
- Add core, wrap, communicate, memory, index to Procfile
Closes #1116
geoffjay
left a comment
There was a problem hiding this comment.
Review: feat(auth): gateway completeness, TenantId extractor, POST /auth/validate, Procfile
LGTM — cannot self-approve, posting as comment.
Stack note
This branch (issue-1116) targets feature/core, which itself targets main. It is the direct parent of the entire core migration stack (#1130 → #1131 → #1132 → #1133 / #1134). Those PRs can stack and merge after this one lands.
What was verified
Procfile — 5 new entries; binary names (communicate, agentd-core, agentd-index, memory, wrap) match the package.name convention already used in the file. Alphabetical ordering is preserved across all entries. ✓
crates/common/src/tenant.rs — two Axum extractors:
TenantId: header present → wraps value; absent + strict →MissingTenantId(400 JSON); absent + permissive →TenantId(String::new()). Logic is correct;MissingTenantIdusesIntoResponsecleanly. ✓OptionalTenantId:Rejection = Infallible, always succeeds, returnsOption<String>. ✓- Tests: both permissive/strict modes combined in one function to avoid env-var races across parallel test threads — same defensive pattern used in
test_get_db_path_respects_agentd_envinstorage.rs. ✓
POST /auth/validate — delegates entirely to the existing AuthUser extractor for auth enforcement, so the 401 path requires no new logic (extractor rejects before the handler body runs). The 200 path is a pure read of auth.user fields — no session mutation, no DB write. ✓
ValidateResponse.validis alwaystruein the 200 body (can never befalse; invalid tokens produce 401 before reaching the handler). Self-documenting for WebSocket upgrade callers. Acceptable.- 3 tests cover: valid token → 200, invalid token → 401, missing token → 401. ✓
crates/core/src/proxy.rs — 3 new entries with port assignments:
memory→ 17008,communicate→ 17010,index→ 17012- No collisions with existing assignments (17001–17006). Module doc table updated to match. ✓
test_proxy_config_new_service_defaultspins the default values;test_proxy_config_all_servicesextended to include new names. ✓
Non-blocking suggestions
-
tenant_required()reads the env var on every request. For a hot extractor path this is a small but repeated syscall. Astd::sync::OnceLockinitialised at first call would be faster and also remove the surprising runtime-change behaviour. Since this is consistent with howAGENTD_ENVis read inget_db_path, no urgency — but worth a follow-up when the tenant module gets wider adoption. -
TenantId(String::new())in permissive mode. Documented, intentional — but service authors usingtenant_id.0as a DB scope key will silently filter by empty string rather than returning all rows or failing. A one-line// NOTE: empty string means no gateway in dev; callers should treat this as "no tenant scope".comment on theNone => Ok(TenantId(String::new())))arm would save future confusion.
Implements all four checklist items from the auth integration foundation issue:
memory(17008),communicate(17010), andindex(17012) toProxyConfig::from_env()with env-override support and expanded testsagentd-common::tenantmodule withTenantId(permissive/strict viaAGENTD_REQUIRE_TENANT) andOptionalTenantId(always succeeds, returnsOption<String>) — 5 tests covering all modesPOST /auth/validatein core service returns{ valid, user_id, organization_id }for fast WebSocket token checks at upgrade time — 3 testscore,wrap,communicate,memory,indexentriesCloses #1116