Bringing the long-running session-feature branch back into main in one deliberate sweep. The branch carried the cluster work that's been live for weeks (cross-cluster CNPG metrics, Grafana w/ Google OAuth, supabase oauth2-proxy, cluster recovery, pg.0.knoe.dev + per-engineer onboarding, GCS-backed CNPG backups via Workload Identity, the env-contamination guard, the Junie brief queue, the cnpg-grafana CSRF + memory-request fixes from today), while main accumulated Junie's parallel knoe-auth Phase 2 OIDC work (full provider surface: discovery, authorize, token, userinfo, JWKS, RS256 signing, code exchange, session services). Key decision: the two branches did COMPETING rebrands off the same starting point (5ba9b63, 2026-04-27): - claude branch (commit b355855, earlier): org.prole.authority.* → dev.knoe.auth.* (artifact renamed to knoe-auth.jar) - main (commit9daa94b, recent): org.prole.authority.* → dev.knoe.authority.* (kept "authority" artifact name) dev.knoe.auth wins: cluster runs from this name, the Maven artifact is already knoe-auth.jar, and the broader rename is the documented namespace direction (per ~/.claude/projects/-Users-chrisfu-dev-knoe-db/ memory/MEMORY.md). All of main's recent Phase 2 OIDC content was ported from authority/src/.../dev/knoe/authority/ into authority/src/.../dev/knoe/auth/ with package declarations rewritten. == File-level resolution summary == Textual conflicts (4): authority/pom.xml - Took our artifactId="auth" - Took our branch's removal of spring-security-kerberos-client (verified: Junie's Phase 2 OIDC code does not import it; the dep was already-dead config) docs/pipeline-phases.md - Took our branch's "Phase 1 not started" status. Main had a misplaced "✅ Complete" with a knoe-auth-Phase-1 commit ref in the autobuild Phase 1 section — different domain. docs/plans/knoe-auth-round-1.md - Took our branch's dev.knoe.auth file table (vs main's dev.knoe.authority listing). Pure rename mismatch. supabase/helm/knoe-supabase/templates/kong/config.yaml - Took our branch's onboard route + plain dashboard wiring. Main had an oauth2proxy.enabled toggle that put oauth2-proxy as a Kong upstream — but the deployed architecture (commit 25f1b2e) has oauth2-proxy in FRONT of Kong, not behind. Main's wrapper reflected an architecture that was never deployed. - Took our branch's removal of basic-auth from dashboard route (queue #15 brief still tracks the matching values.yaml / kong/deployment.yaml cleanup). Java tree reconciliation (44 file-pairs): 20 dual-path source files + 2 dual-path tests Body-identical between main's authority/ and our branch's auth/ after stripping package decls — main's commit9daa94bwas a pure rebrand. Took our branch's auth/ version for all 22. 8 main-only source files (Phase 2 OIDC), ported into auth/: web/JwksController.java web/OidcAuthorizeController.java web/OidcDiscoveryController.java web/OidcTokenController.java web/OidcUserInfoController.java session/OidcCodeService.java session/OidcTokenService.java session/SessionService.java 12 main-only test files, ported into auth/: HealthControllerTest.java enroll/EnrollValueTypesTest.java enroll/EnrollmentControllerTest.java enroll/TotpServiceTest.java kerberos/KadminClientTest.java kerberos/KerberosSpnegoResultTest.java web/LoginControllerTest.java admin/AdminControllerTest.java user/PrincipalNormalizerTest.java regression/IdentityRegressionTest.java session/OidcCodeServiceTest.java session/SessionServiceTest.java Port mechanics: read main:authority/...<file> via git show, then sed rewrite `package dev.knoe.authority` → `package dev.knoe.auth` and `import dev.knoe.authority` → `import dev.knoe.auth`. Body content unchanged. authority/src/main/java/dev/knoe/authority/ — DELETED (duplicate) authority/src/test/java/dev/knoe/authority/ — DELETED (duplicate) == Verification == - grep -rln '<<<<<<<' across .java/.md/.yaml/.yml/.sh/.xml/.tpl: clean - find authority/src -path '*/dev/knoe/authority*': empty (subtree gone) - grep 'package dev.knoe.authority' across repo: clean - bash -n install.sh deploy.sh etc/preflight_kubecontext.sh: clean - git ls-files -u | wc -l: 0 unmerged paths - helm lint supabase/helm/knoe-supabase: pre-existing failure on studioIngress.enabled undefined in values.yaml (introduced by Junie on main; unrelated to this merge — flagging as follow-up). == Followups (carried into TODO ranked queue or noted here) == - helm lint failure: studioIngress block in values.yaml is missing enable flag; templates/studio/{ingress,oauth2proxy-deployment, oauth2proxy-service}.yaml all reference studioIngress.enabled with no default. Pre-existing on main; not introduced by this merge. - The five Junie briefs filed on this branch are now reachable from main at docs/plans/junie/{02,06,07,13,15}-*.md. Junie can pick them up in any order. - knoe-auth Phase 2 OIDC source (now at dev.knoe.auth.*) is not yet deployed to the cluster. Deployment is its own task. - The branch claude/crazy-bose-fec256 stays in place (worktree at .claude/worktrees/crazy-bose-fec256 may have ongoing context for Claude Code sessions). Safe to delete once next session starts cleanly from main. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5.6 KiB
Engineer onboarding — first-day checklist
Welcome. This doc gets you from "I just got an onboarding link" to "psql is open and I'm productive". Should take ~5 minutes.
Phase 1 (current). Each engineer has a per-name postgres role with a temp password (24h) delivered via a one-time link. Phase 2 (queued) replaces the password mechanism with libpq OAUTHBEARER (Google sign-in). Your role name persists; only the connection string changes when Phase 2 lands.
What you should have
- An onboarding link that looks like
https://db.0.knoe.dev/onboard.html#user=...&pw=...&exp=..., delivered by chrisfu via either:- A Gmail message to your
@knoey.commailbox, or - A QR code shown on screenshare during a Signal call.
- A Gmail message to your
- A clone of the
knoe-dbrepo.
If you don't have either, ping chrisfu.
Step 1 — Open the link / scan the QR
Click the URL (or scan the QR with your phone camera). The page at
db.0.knoe.dev/onboard.html decodes the URL fragment client-side and
displays:
- Your temporary password — with a [Copy] button
- Your psql connection string — pre-filled with your role name, also [Copy]
- A bootstrap one-liner that fetches the CA cert and connects you
- Inline
\passwordrotation instructions
Save the password to your personal 1Password (or whichever password manager you use). The page strips the password from your browser history on first render, but DO NOT close it before saving — the page is one-shot.
Step 2 — Connect and rotate
Clone the repo if you haven't, then connect:
git clone git@git.knoe.dev:knoey.dev/knoe-db.git
cd knoe-db
psql "host=pg.0.knoe.dev port=5432 user=$YOUR_USERNAME dbname=postgres \
sslmode=verify-full sslrootcert=etc/knoe-db-ca.crt"
Paste the temporary password when prompted.
Rotate immediately:
postgres=> \password
Enter new password: <type a strong password you generate locally>
Enter it again: <repeat>
postgres=> -- save the new password to your personal 1Password.
postgres=> -- everything from here uses YOUR password.
Why immediately? The temp VALID UNTIL is 24h; if you don't rotate before
then, you'll be locked out (chrisfu can rerun the onboard script to issue a
fresh temp).
Step 3 — What you can do as knoe_developer
Your role is a member of the knoe_developer group. Grants:
| Schema | Permission | Notes |
|---|---|---|
knoe |
SELECT, INSERT, UPDATE, DELETE |
Application schema |
public |
SELECT, INSERT, UPDATE, DELETE |
Same |
auth |
SELECT only |
Read-only on Supabase GoTrue tables |
storage |
SELECT only |
Read-only on Supabase storage tables |
extensions |
USAGE |
Lets you reach extensions.pg_stat_statements etc. |
What you can't do:
- Drop / truncate
auth.*orstorage.*(read-only on those by design). CREATE ROLE,CREATE EXTENSION(postgres superuser only).- Connect from outside the cluster as
postgres,supabase_admin, etc. (those roles are pinned to RFC1918 bypg_hba.conf).
Need broader access? File an issue or ping chrisfu — easier to extend the group than mint per-engineer overrides.
Step 4 — Rust apps (if applicable)
Same connection string in sqlx / tokio-postgres / deadpool-postgres:
let url = format!(
"postgres://{user}:{password}@pg.0.knoe.dev:5432/postgres\
?sslmode=verify-full&sslrootcert={ca}",
user = std::env::var("KNOE_PG_USER")?,
password = std::env::var("KNOE_PG_PASSWORD")?,
ca = std::env::current_dir()?.join("etc/knoe-db-ca.crt").display(),
);
let pool = sqlx::PgPool::connect(&url).await?;
For deployed services (not your laptop): Phase 2 swaps the user/password env vars for an OIDC token. The connection string skeleton stays the same.
Step 5 — Studio access (web UI, optional)
Open https://db.0.knoe.dev/ in any browser, sign in with your @knoey.com
Google account. Studio is the same database; you can use it for ad-hoc
queries, table inspection, RLS rule editing. Most of what you need is in the
SQL editor.
Troubleshooting
-
pg_hba.conf rejects connection ... no encryption— you setsslmode=disable. Useverify-full(withsslrootcert=etc/knoe-db-ca.crt) or at minimumrequire. -
password authentication failed— wrong password (typo when copy-paste, or temp expired). Run psql with\passwordonce you're in, OR ping chrisfu to rerun the onboard script. -
role "<u>" is not permitted to log in— yourVALID UNTILlapsed. Ask for rotation. -
Connection times out — DNS for
pg.0.knoe.devmay not have propagated on your network yet. Trydig pg.0.knoe.dev. Should resolve to34.106.156.196(or whatever the current LB IP is). -
server certificate for "..." does not match host name "pg.0.knoe.dev"— you're usingverify-fullbut the CA cert in your repo is stale (CNPG rotated the CA).git pulland try again, or fetch the fresh cert from chrisfu.
Related
docs/db-access.md— the underlying access architecture (LB, pg_hba, role grants, Phase 2 plan).- The plan file (live, not in git) at
~/.claude/plans/we-re-continuing-work-on-happy-toast.mdfor chrisfu — has the design rationale for why this delivery channel was chosen over a shared vault. etc/onboard_engineer.sh— the script chrisfu runs to provision your role and emit your URL. Same script handles--rotateand--revoke.