- Include w_schedules and w_task_executions DDL in admin initial migrations for both SQLite and PostgreSQL dialects
- Remove driver-specific migration registrations from driver_asynq_worker and driver_asynq_cron
- Fix missing table error when running in Zero-Redis standalone mode without Asynq
- Update white paper table ownership mapping and ensure test cleanup
- implement route whitelist registration and wildcard matching in RouterExtension
- add cookie store session fallback when Redis is disabled in driver_http
- actively register public auth endpoints to whitelist in auth plugin
- update user handlers to persist session and clear cookie on logout
- document router whitelist mechanism in AGENTS.md and new-api skill
* autoresearch iter 23: fail-closed auth guarding for user/message_gateway
Both plugins resolve contracts.AuthService in Apply to build their route
middleware, but declared only DBService in Inject(). The kernel gates a
plugin's Apply solely on declared deps, and cmd/app.go registers user
before auth, so user mounted first, core.Inject failed, and loginMW
silently degraded to a pass-through closure — leaving /api/v1/user
change-password, profile and access-tokens unguarded. message_gateway
was saved only by its later list position.
Declare AuthService in Inject() for both, and pin the property with a
reconcile-level test that mirrors production registration order and
asserts the real auth middleware reaches the route table.
* autoresearch iter 24: make auth middleware fallbacks fail closed
user, message_gateway and admin each fell back to a c.Next() closure when
contracts.AuthService could not be resolved, so a route would be served as
if authenticated. For admin this is reachable at runtime: OnDispose calls
service.ResetServices(), which nils the global the per-request guard reads,
so requests still in flight during dispose bypass authorization entirely.
Add ginutil.AuthUnavailable() and bind every fallback to it, with a test
that drives each plugin's registered guard without an auth service present
and asserts the request is aborted rather than passed through.
* chore(autoresearch): log iter 23 (fail-open auth ordering, proven)
* autoresearch iter 24 follow-up: let staticcheck infer the auth guard type
* docs(autoresearch): log iters 24-25 and lessons 9-11 (declared-dep bug class, gate discipline)
24 of the 96 nolint directives were dead: they covered findings that no
longer exist. A stale suppression is not inert — it silently claims any
future finding for that linter in that scope, so a real problem raised
there would vanish without anyone noticing. Explanatory prose was kept as
ordinary comments.
Two directives proved load-bearing under the project gate even though
nolintlint reported them unused, and removing them exposed verified
contextcheck false positives: App.Run does forward a sigCtx derived from
the caller's context to Start, and the migration lock renewal must keep
its own deadline because the task context may already be canceled. Both
were restored, narrowed to the live linter, and given the reason the
originals lacked.
downloadMedia created a fresh os.MkdirTemp for every private message carrying
a photo or document, and no code path anywhere reads Attachment.Path, so each
message permanently grew the disk while burning a Bot API download. The
handler now removes the directory once onInbound returns.
No mechanical proof is possible here: exercising downloadMedia needs a live
telebot download. Verified by reading every consumer of InboundMessage
.Attachments instead.
Note: iter 20's commit also captured an in-flight edit to
docs/superpowers/plans/2026-08-29-cordis-config-extension.md belonging to a
concurrent session, because it used 'git add -A'. Content is intact; later
iterations stage explicit paths only.
telebot types LongPoller.Timeout as time.Duration and sends
int(timeout / time.Second) to getUpdates, so the literal 10 meant ten
nanoseconds: Telegram received timeout=0, long polling never held the
connection, and the adapter polled the Bot API in a tight loop instead.
Use 10 seconds and extract the settings so the conversion is asserted.
The adapter also has no media temp-dir cleanup (downloadMedia creates an
MkdirTemp per attachment and nothing removes it); that is left as a separate
change rather than bundled here.