Absorb the composition-root Config/BuildLogger bootstrap into toolbelt/app #4
Labels
No labels
needs-info
needs-triage
ready-for-agent
ready-for-human
wayfinder:grilling
wayfinder:map
wayfinder:prototype
wayfinder:research
wayfinder:task
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Depends on
#3 Absorb the config reexport layer into toolbelt/config
ginjiruu/toolbelt
Reference
ginjiruu/toolbelt#4
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Question
Should
toolbelt/appship a standardConfig-struct +BuildLoggerbootstrap soapp.goshrinks to feature wiring?Consumers and the example all hand-write in
internal/app/app.go: aConfigstruct (~16 fields),NewConfig()reading every field viaconfig.ReadFieldString, and aBuildLogger()(~30 lines byte-identical across consumers). This passes the "example proves it" boundary.Decisions this ticket resolves:
toolbelt/appprovide the Config-reading + logger construction, or is it a helper the app calls (keeping the typedConfigstruct per-app)?ReadField*functions andBuildLogger)? Depends on the config ticket's answer.Blocked by the config-reexport ticket: this
Configstruct reads through the reexport layer, so its shape follows that decision.Resolve with
/grilling+/domain-modeling. On close, write the plan todocs/plans/and reshape the relevantexample/surface.Resolved via
/grilling+/domain-modeling.Decision:
toolbelt/appowns the entire composition-root bootstrap.New(ctx, cfg *config.Config, opts)reads its platform fields from the config object internally and builds the logger (exportedapp.BuildLogger(level, format)); the startup summary moves intoNew;Component.Configbecomes the*config.Configobject. Features self-populate atRegister—authn.New(opts)loses its six OIDC fields and the logger arg, reading both fromc.Config/c.Logger;web.New()/kanban.New()drop the logger arg.app.goshrinks toNewKanbanApp(ctx, config.App)+ feature wiring; the flatConfigstruct,NewConfig(), and all fiveBuildLoggercopies die.Answer to the ticket's decision 1:
toolbelt/appprovides the Config-reading + logger construction outright (not a helper the app calls), because the per-app typed struct is a zero-logic passthrough over byte-identical field names.Answer to the ticket's decision 2 (the seam): the seam is the generated
config.Appobject (ticket #3);BuildLoggerlives intoolbelt/app; config reads flow throughconfig.App.ReadField*. Nothing is re-exported.Coordination: platform field definitions follow ticket #12's per-package KCL fragments;
toolbelt/app's field symbols must be referenceable from the merged registry.Ripple (consumer breaks, migration out of scope):
app.Newsignature(ctx, logger, cfg, opts)→(ctx, cfg, opts);authn.New(logger, opts)→authn.New(opts)with six OIDCOptionsfields removed;configpackage-level API removed per #3.Plan:
docs/plans/app-bootstrap.md. Example reshape deferred to the implementation session shared with the config ticket.Resolution recorded in the decision comment; plan at docs/plans/app-bootstrap.md.
Coordination from #12 (per-package KCL config fragments): authn ships its own KCL fragment. When this ticket's authn absorption lands, add authn/schema.k declaring the standard OIDC schema (issuer, client_id, client_secret, redirect_uri, supported_algs, group_scope) with service-neutral defaults, and have apps compose it via 'oidc: authn.OIDC = authn.OIDC {}' (KCL import, per #12's KCL-native resolution). The OIDC schema is generic and defined once; only the values vary per app. #12 itself keeps OIDC app-authored; this ticket owns moving it into authn.