Skip to content

fix(admin,cfg): promote adminTTL const to configurable cfg.AdminTokenTTL (TD-010)#7

Merged
devonartis merged 1 commit into
developfrom
fix/td-010-admin-token-ttl-config
Apr 10, 2026
Merged

fix(admin,cfg): promote adminTTL const to configurable cfg.AdminTokenTTL (TD-010)#7
devonartis merged 1 commit into
developfrom
fix/td-010-admin-token-ttl-config

Conversation

@devonartis

Copy link
Copy Markdown
Owner

Summary

Deletes the magic-number const adminTTL = 300 from internal/admin/admin_svc.go and replaces it with an operator-configurable field driven by AA_ADMIN_TOKEN_TTL. Default preserved as a named const (defaultAdminTokenTTL = 300) in cfg.go so no magic number leaks into Load().

Resolves: TD-010 (marked RESOLVED in TECH-DEBT.md).

What changed

Production:

  • cfg.Cfg.AdminTokenTTL int added, env AA_ADMIN_TOKEN_TTL, default defaultAdminTokenTTL = 300 (seconds)
  • admin.NewAdminSvc signature extended with tokenTTL int parameter; stored on the struct, used in Authenticate()
  • cmd/broker/main.go passes c.AdminTokenTTL through

Tests:

  • admin_svc_test.go: added testAdminTokenTTL = 300 fixture const, updated both newTestAdminSvc* helpers, updated assertion
  • admin_hdl_test.go: both NewAdminSvc call sites updated, assertion updated
  • app_hdl_test.go + handler_test.go: NewAdminSvc calls updated (orthogonal — these tests don't check TTL, just pass 300)
  • cfg_test.go: added TestLoad_AdminTokenTTLDefault + TestLoad_AdminTokenTTLCustom

Why int seconds and not time.Duration

The existing TTL fields (DefaultTTL, MaxTTL, AppTokenTTL) all use int seconds. Adding one time.Duration field would create two conventions in the same cfg package and leak into every caller that passes the field through. A future cleanup (proposed TD-CFG-003) can migrate all TTL fields to time.Duration together — mixing conventions mid-stream would be worse than preserving the existing one.

CI-matrix-via-unit-test

The existing resp.ExpiresIn != testAdminTokenTTL assertion in admin_svc_test is the unit-level equivalent of a config-matrix behavioral test for this field — it proves the full cfg.AdminTokenTTL -> AdminSvc.tokenTTL -> TknSvc.Issue -> claims.Exp-Iat flow at test time. No new CI infrastructure needed for this particular field because it's all inside one package boundary.

Test plan

  • go build ./... clean
  • go vet ./... clean
  • gofmt -l returns empty
  • go test ./... — 15/15 packages pass locally (full suite, not just internal/)
  • CI: all 13 gates + gates-passed aggregator green

Scope boundaries

  • Does NOT migrate other TTL fields to time.Duration (separate proposed TD-CFG-003)
  • Does NOT add a new CI config-matrix job (unit test inside admin package covers it)
  • Does NOT touch docs that mention adminTTL = 300 (e.g. docs/credential-model.md:154) — separate doc sweep

Action plan: .plans/specs/2026-04-10-td-010-action-plan.md

…TTL (TD-010)

Delete the magic-number const `adminTTL = 300` in internal/admin/admin_svc.go
and replace with an operator-configurable field driven by AA_ADMIN_TOKEN_TTL.
Default preserved as a named const (defaultAdminTokenTTL = 300) so no magic
number leaks into cfg.Load(). Operators tune admin JWT lifetime without
recompiling.

Production code:
- internal/cfg/cfg.go: added AdminTokenTTL int field (seconds), named const
  defaultAdminTokenTTL, env var AA_ADMIN_TOKEN_TTL, inline doc comment
- internal/admin/admin_svc.go: deleted const adminTTL, added tokenTTL field
  to AdminSvc, NewAdminSvc signature extended with tokenTTL int parameter,
  Authenticate() now issues with s.tokenTTL instead of the hardcoded const
- cmd/broker/main.go: NewAdminSvc wiring passes c.AdminTokenTTL

Tests:
- internal/admin/admin_svc_test.go: added testAdminTokenTTL = 300 fixture
  const, updated both newTestAdminSvc helpers to pass it, updated assertion
  to compare against the fixture instead of the deleted const
- internal/admin/admin_hdl_test.go: same pattern — both NewAdminSvc calls
  pass testAdminTokenTTL, assertion compares against it
- internal/app/app_hdl_test.go: NewAdminSvc call updated (passes 300
  literal; app tests don't care about the value)
- internal/handler/handler_test.go: same — NewAdminSvc call updated
- internal/cfg/cfg_test.go: added TestLoad_AdminTokenTTLDefault and
  TestLoad_AdminTokenTTLCustom covering default and override paths

The existing assertion `resp.ExpiresIn != testAdminTokenTTL` in admin_svc_test
is the unit-level equivalent of a config-matrix behavioral test for this
field — it proves the full cfg.AdminTokenTTL -> AdminSvc.tokenTTL ->
TknSvc.Issue -> claims.Exp-Iat flow at test time.

Int seconds (not time.Duration): the existing TTL fields (DefaultTTL,
MaxTTL, AppTokenTTL) all use int seconds. Adding one time.Duration field
would create two conventions in the same cfg package and leak into every
caller. A future cleanup (proposed TD-CFG-003) can migrate all TTL fields
to time.Duration together — mixing conventions mid-stream would be worse
than preserving the existing one.

Validation: go build ./..., go vet ./..., gofmt -l, go test ./... all
green across 15 packages (includes cmd/broker now that main.go is touched).

Marks TD-010 RESOLVED in TECH-DEBT.md.

Action plan: .plans/specs/2026-04-10-td-010-action-plan.md
@devonartis devonartis merged commit 2a7d96c into develop Apr 10, 2026
17 checks passed
@devonartis devonartis deleted the fix/td-010-admin-token-ttl-config branch April 10, 2026 19:02
devonartis added a commit that referenced this pull request Apr 10, 2026
Catches docs up with the configuration defaults landed in PR #6 (TD-TOKEN-001,
TD-CFG-001, TD-CFG-002) and PR #7 (TD-010). Docs were previously teaching
the old hardcoded brand values in example JWT payloads, SPIFFE URIs,
filesystem paths, and env var defaults. Now they reflect the current
defaults as shipped.

Direct push to develop (not PR) per explicit user instruction — this is
documentation chasing production defaults, not new code. No Go source
changes.

Sweep patterns (bulk sed across docs/**/*.{md,yaml,yml,svg}):
- agentauth.local        -> agentwrit.local    (matches cfg.TrustDomain default)
- agentauth.db           -> data.db            (matches cfg.DBPath default)
- /etc/agentauth/        -> /etc/broker/       (matches cfg.configfile.go search path)
- /var/lib/agentauth/    -> /var/lib/broker/   (consistent data-dir naming)
- ~/.agentauth/          -> ~/.broker/         (matches cfg.configfile.go home fallback)
- "iss": "agentauth"     -> "iss": "agentwrit" (example JWT payloads)
- "aud": "agentauth"     -> "aud": "agentwrit" (example JWT payloads)
- AgentAuth              -> AgentWrit          (brand prose)
- agentauth (bare)       -> agentwrit          (brand prose)
- AGENTAUTH              -> AGENTWRIT          (any uppercase)

Preserved (not changed):
- github.com/devonartis/agentauth — Go module path + GitHub clone URLs
  (getting-started-user.md lines 74, 104). Module path rename is gated on
  the GitHub repo rename, which is separate work.
- CHANGELOG historical entries (not touched)
- tests/*/evidence/*.md historical records (not touched — they're in
  tests/ not docs/, so the sweep didn't reach them anyway)

Renames:
- docs/agentauth-explained.md -> docs/agentwrit-explained.md

Targeted updates:
- docs/credential-model.md:154 — the "hardcoded adminTTL = 300, see TD-010"
  text replaced with the new reality: "5 minutes default, operator-configurable
  via AA_ADMIN_TOKEN_TTL." TD-010 is now RESOLVED in TECH-DEBT.md so the
  reference was stale.

Scope: ~20 doc files + 1 file rename. No code, no tests, no scripts.
devonartis added a commit that referenced this pull request Apr 12, 2026
Includes:
- PR #6: hardcoded identity audit fixes (TD-TOKEN-001/002/003, TD-CFG-001/002, TD-TEST-001)
- PR #7: adminTTL → cfg.AdminTokenTTL (TD-010)
- PR #8: aactl → awrit binary rename (TD-CLI-001)
- PR #11: docs audit P1/P2 corrections + docs-layout-archon-style sweep
- PR #12: runtime rebrand alignment — problemdetails URN, obs metrics,
  awrit init config path (TD-RUNTIME-001, TD-OBS-001, TD-CLI-002),
  GitHub repo rename agentauth → agentwrit, Go module path rename,
  README/CONTRIBUTING/docs sweep, CI brand-alignment gate
- Direct-to-develop: brand sweep docs (684083b)

Stripped 16 dev-only paths: MEMORY.md, FLOW.md, TECH-DEBT.md,
MEMORY_ARCHIVE.md, CLAUDE.md, AGENTS.md, COWORK_SESSION.md,
COWORK_DOCS_AUDIT.md, .plans/, .claude/, .agents/, audit/, adr/,
.vscode/, .active_module, generate_pdf.py.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant