feat(cli): tapir report — Stage-0 usage gate query
ActiveWeeks computes per-user distinct active weeks (reads login_events UNION acts summary_actions) for the gate (VISION/ADR-016: usage in >=2 distinct weeks). Because the user-owned tables are FORCE RLS under a non-superuser owner, a single cross-user query is deny-all; instead it enumerates users from the un-RLS'd identity map and counts each inside withUser — no privilege escalation, no policy change. `tapir report` prints the per-user table and the pass/fail verdict (needs only TAPIR_DB_DSN). Pure formatter + store query are unit-tested, including the cross-table shared-week dedup. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
|
||||
"gitea.d-ma.be/mathias/tapir/internal/adapters/store"
|
||||
)
|
||||
|
||||
// gateThreshold is the Stage-0 gate (VISION/ADR-016): usage in >= 2 distinct
|
||||
// weeks. The gate passes when any user reaches it.
|
||||
const gateThreshold = 2
|
||||
|
||||
// runReport prints the Stage-0 usage gate: per-user distinct active weeks (reads
|
||||
// UNION acts) and the pass/fail verdict. Read-only, cross-user — needs only
|
||||
// TAPIR_DB_DSN (not TAPIR_USER_ID; the report enumerates all users itself).
|
||||
func runReport(ctx context.Context, _ []string) error {
|
||||
dsn := os.Getenv(envDSN)
|
||||
if dsn == "" {
|
||||
return fmt.Errorf("%s is required", envDSN)
|
||||
}
|
||||
s, err := store.New(ctx, dsn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer s.Close()
|
||||
|
||||
rows, err := s.ActiveWeeks(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return formatReport(os.Stdout, rows)
|
||||
}
|
||||
|
||||
// formatReport renders the per-user week counts and the gate verdict. Pure: no DB,
|
||||
// no env — so the layout and verdict logic are unit-testable without Postgres.
|
||||
func formatReport(w io.Writer, rows []store.UserActiveWeeks) error {
|
||||
if len(rows) == 0 {
|
||||
_, err := fmt.Fprintln(w, "no users yet")
|
||||
return err
|
||||
}
|
||||
|
||||
tw := tabwriter.NewWriter(w, 0, 4, 2, ' ', 0)
|
||||
_, _ = fmt.Fprintln(tw, "USER\tNAME\tACTIVE_WEEKS\tGATE")
|
||||
passed := false
|
||||
for _, r := range rows {
|
||||
gate := "-"
|
||||
if r.ActiveWeeks >= gateThreshold {
|
||||
gate = "PASS"
|
||||
passed = true
|
||||
}
|
||||
_, _ = fmt.Fprintf(tw, "%s\t%s\t%d\t%s\n", r.UserID, orDash(r.DisplayName), r.ActiveWeeks, gate)
|
||||
}
|
||||
if err := tw.Flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
verdict := fmt.Sprintf("\nGate (usage in >= %d distinct weeks): NOT YET MET\n", gateThreshold)
|
||||
if passed {
|
||||
verdict = fmt.Sprintf("\nGate (usage in >= %d distinct weeks): PASSED\n", gateThreshold)
|
||||
}
|
||||
_, err := fmt.Fprint(w, verdict)
|
||||
return err
|
||||
}
|
||||
Reference in New Issue
Block a user