Skip to content

feat(obs): apiHelpers on 5 more routes + drop "Commander" default name#168

Merged
operatoruplift merged 1 commit intomasterfrom
apihelpers-batch-2
Apr 27, 2026
Merged

feat(obs): apiHelpers on 5 more routes + drop "Commander" default name#168
operatoruplift merged 1 commit intomasterfrom
apihelpers-batch-2

Conversation

@operatoruplift
Copy link
Copy Markdown
Owner

Trust-gate coverage 16/44 → 21/44

Continuing the broadening from #167. Five more routes adopt the withRequestMeta / errorResponse / validationError pattern.

Route Lines What it does
app/api/gold/route.ts 17 Gold price + balance + transactions (Oro GRAIL)
app/api/risk/route.ts 19 Webacy risk preflight
app/api/auth/login/route.ts 30 Supabase email/password sign-in
app/api/auth/signup/route.ts 36 Supabase email/password sign-up
app/api/sns/resolve/route.ts 35 Bonfida .sol domain resolution

Each adopts withRequestMeta for the X-Request-Id header. The two auth routes plus risk also pick up validationError() for clean 400 responses with { missing: [...] } details. Gold + risk pick up errorResponse() for the 500 path.

Auth routes are the entry point for every signed-in session, so getting them on the same request-id contract is high value for support diagnostics.

Bonus: drop "Commander" default name

app/api/auth/signup/route.ts was setting:

data: { display_name: name || 'Commander' }

PR #163 already removed "Commander" from the dashboard h1 ("Good {greeting}, Commander."). PR #166 cleaned up the rest of the sci-fi cosplay vocabulary. Signup was the last surface where a fresh user got "Commander" as their default display name.

Now: derives a default from the email's local part (jane.doe@x.com"jane.doe"), falling back to "Friend" if email is missing.

Verified

pnpm exec tsc --noEmit
# exit 0

pnpm check
trust-gate: clean. 21/44 route files import @/lib/apiHelpers and all call withRequestMeta.   <- was 16/44
check: 3 passed, 0 failed, 0 skipped

Net diff

5 files changed, 45 insertions(+), 20 deletions(-)

Rollback

Single git revert.

Trust-gate coverage 16/44 -> 21/44, plus one more sci-fi cosplay
residual fixed.

## Routes adopting apiHelpers

| Route | Lines |
|---|---|
| app/api/gold/route.ts | 17 |
| app/api/risk/route.ts | 19 |
| app/api/auth/login/route.ts | 30 |
| app/api/auth/signup/route.ts | 36 |
| app/api/sns/resolve/route.ts | 35 |

Each adopts `withRequestMeta` for the X-Request-Id header. The two
auth routes plus risk also pick up `validationError()` for clean 400
responses with `{ missing: [...] }` details. Gold + risk pick up
`errorResponse()` for the 500 path.

## Drop "Commander" default name

`app/api/auth/signup/route.ts` was setting

  data: { display_name: name || 'Commander' }

PR #163 already removed "Commander" from the dashboard h1 ("Good
{greeting}, Commander."), and #166 cleaned up the rest of the
sci-fi cosplay vocabulary. Signup was the last surface where a fresh
user got "Commander" as their default display name.

Now: derives a default from the email's local part (jane.doe@x.com
-> "jane.doe"), falling back to "Friend" if email is missing.

## Verified

- pnpm exec tsc --noEmit: clean
- pnpm check: 3 passed, 0 failed
- trust-gate: 21/44 route files (was 16/44)

## Rollback

Single git revert. 5 files.
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 27, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
website Ready Ready Preview, Comment Apr 27, 2026 8:20am

@operatoruplift operatoruplift merged commit 1a8d5c5 into master Apr 27, 2026
4 checks passed
operatoruplift added a commit that referenced this pull request Apr 27, 2026
)

Continuing the broadening from #167 / #168. Five more routes adopt the
withRequestMeta / errorResponse / validationError pattern.

| Route | Lines | Audience |
|---|---|---|
| app/api/waitlist/route.ts | 40 | Public signup |
| app/api/access/check/route.ts | 52 | Beta access gate |
| app/api/access/verify-payment/route.ts | 62 | On-chain payment confirm |
| app/api/integrations/google/connect/route.ts | 65 | OAuth start |
| app/api/integrations/google/callback/route.ts | 59 | OAuth complete |

The two integrations routes are notable because they redirect to
`/integrations?error=...` instead of returning JSON. Both now append
`&ref=<requestId>` to the redirect URL so support can correlate the
oauth-failure URL the user sees with the server log line, and
`withRequestMeta` still attaches `X-Request-Id` to the redirect.

The Google callback also gets a structured one-line JSON log on the
error path (matching the shape `errorResponse()` would produce, but
in-line because the response is a redirect, not a JSON envelope).

## Verified

- pnpm exec tsc --noEmit: clean
- pnpm check: 3 passed, 0 failed
- trust-gate: 26/44 route files (was 21/44)

## Rollback

Single git revert. 5 files.
operatoruplift added a commit that referenced this pull request Apr 27, 2026
)

Continuing the broadening from #167 / #168 / #169. Four more routes
adopt the withRequestMeta / errorResponse / validationError pattern.

| Route | What it does |
|---|---|
| app/api/profile/briefing/route.ts (GET + PUT) | Daily-briefing toggle on Profile |
| app/api/tools/notes/route.ts | Tier-1 notes tool (Supabase) |
| app/api/tools/tasks/route.ts | Tier-1 tasks tool (Supabase) |
| app/api/tools/imessage/route.ts | Photon iMessage send |

The four /api/tools/* routes already had a clean honest-status flow
(503 + action_required when an adapter is inactive, no fake success
on demo callers); this PR adds the X-Request-Id + structured error
envelope on top so the diagnostic line in CI logs and the response
header agree on the request identifier.

The imessage route's adapter-not-configured response now also carries
the canonical fields (errorClass: 'provider_unavailable', requestId,
timestamp, nextAction) so the chat UI can render it the same way it
renders calendar/gmail provider errors.

## Verified

- pnpm exec tsc --noEmit: clean
- pnpm check: 3 passed, 0 failed
- trust-gate: 30/44 route files (was 26/44)

## Rollback

Single git revert. 4 files.
operatoruplift added a commit that referenced this pull request Apr 27, 2026
Locks in the plain-English voice and removed-feature-claim guarantees
shipped across PRs #147-#168. If a future PR drifts back toward dev or
sci-fi vocabulary, CI fails before merge.

## tests/e2e/consumer-copy.spec.ts (new)

Six scoped specs, each asserts BOTH the new consumer phrasing IS
present AND the retired developer/jargon phrasing is absent.

| Test | Surface | Asserts |
|---|---|---|
| homepage hero | / | "stay in charge" + "Try it free" present |
| navbar labels | / | "HOW IT WORKS / HELPERS / WATCH DEMO" present |
| /paywall | /paywall | "Drafts your replies" + "Pick a plan" present |
| /store | /store | h1 "Helpers", "Free in beta", "Install" button |
| /pricing | /pricing | "Pricing for teams" + "Personal plans start free" |
| OG metadata | / | meta description leads with daily job |

Each test also runs `assertNoBannedPhrases()` against the rendered DOM
text. The banned list covers:
- Sci-fi cosplay: Commander, Uplift Core, Warp Network, Blackwall,
  CodePilot Pro, Founder Ops, Gold Agent, DeepRepo Orchestration
- Dev jargon: Multi-agent orchestration, AI Operating System,
  On-chain Merkle audit trail, agent orchestration, Self-Hosted
- Council fabrication: LLM Council, 5 agents debate, Chairman,
  Contrarian, First Principles thinker, Expansionist, Outsider

Plus the existing chat-honesty.spec.ts (which already covered
/chat + /paywall + /swarm against the council list) is now
unconditionally part of the CI hermetic spec set.

## .github/workflows/ci.yml

Both consumer-copy.spec.ts and chat-honesty.spec.ts are added to the
hermetic Playwright run. Both can fail the PR check.

## Verified

- pnpm exec tsc --noEmit: clean
- pnpm check: 3 passed, 0 failed
- pnpm exec playwright test consumer-copy.spec.ts: 6 passed (30.3s)

## Rollback

Single git revert. 2 files.
operatoruplift added a commit that referenced this pull request Apr 28, 2026
…s) (#186)

The /settings page had a 17-line useEffect that read localStorage at
mount and called 7 separate setStates. Replaced with a single useMemo
lazy load + lazy-initializer useStates that pull from it.

The theme effect stays as a real DOM side effect (sets data-theme on
<html>), but it now only reacts to `theme` state changes - no
synchronous setState in the effect body.

The 'Commander' default display name (last sci-fi cosplay residual,
post-#163/#168) became 'Friend'.

AdvancedSettings inner panel had its own setState-in-effect that
read advanced_mode from localStorage. Hoisted to a lazy initializer
the same way.

| Change | File:line |
|---|---|
| 7-setState mount effect → useMemo + lazy initializers | settings/page.tsx:38-56 |
| 'Commander' default → 'Friend' | settings/page.tsx:23 |
| AdvancedSettings setAdvancedMode in effect → lazy initializer | settings/page.tsx:412-417 |

## Verified

- pnpm exec tsc --noEmit: clean
- pnpm check: 3 passed, 0 failed
- pnpm lint: 85 problems / 19 errors (was 87 / 21)

## Rollback

Single git revert.
operatoruplift added a commit that referenced this pull request Apr 28, 2026
The README was last updated before the consumer-copy sweep (PRs
#152-#168), so it still:
- Used "Your Life, Automated." tagline (retired)
- Called the product "a local-first AI agent operating system"
  ("AI Operating System" is on the banned-phrases list, #158)
- Pitched "Multi-agent swarms" / "Agent marketplace" (retired in
  #156, #154)
- Had only the boilerplate Next.js create-next-app text below the
  header, no project-specific guidance

Now reads in the same voice as the homepage: "AI for your inbox and
calendar. You stay in charge." Adds:

- Project-layout section (app/, src/sections/, src/components/, lib/, tests/e2e/)
- CI checks summary (the 11 hermetic specs that block PRs)
- Mention of the honesty regression tests that lock in PRs #147-#185

The banned-phrase grep on README is now clean except for the line
that explicitly DOCUMENTS what those tests guard against, which is
fine.

## Verified

- pnpm exec tsc --noEmit: clean
- pnpm check: 3 passed, 0 failed
- README banned-vocab grep: only matches the "tests guard against" line

## Rollback

Single git revert.
operatoruplift added a commit that referenced this pull request Apr 28, 2026
…#188)

The sitemap was missing three public consumer surfaces that PRs
#152-#168 rewrote into shape:

- /store - the helpers store landing page (#154)
- /docs - the in-repo /docs help site (#158 metadata + nav rename)
- /press-kit - the press kit + media-resources page

Search engines couldn't discover them, so the consumer pitch on
those pages wasn't being indexed.

Also:
- Hosts the URL prefix in a HOST const so future entries can't drift
- Bumps homepage changeFrequency from `yearly` to `weekly` to match
  reality (the consumer copy + OG image have shipped repeatedly)
- Adds a comment block explaining the priority ordering

## Verified

- pnpm exec tsc --noEmit: clean
- pnpm check: 3 passed, 0 failed
- After deploy, /sitemap.xml will list 10 URLs (was 7)

## Rollback

Single git revert.
operatoruplift added a commit that referenced this pull request Apr 28, 2026
…190)

Last residual of the dev-jargon vocabulary that #152-#168 retired.
Four user-visible surfaces still said "Local-first":

| File | Surface | Was -> Now |
|---|---|---|
| app/layout.tsx (JSON-LD) | Google search snippet description | "Local-first AI agent platform with secure, private memory. Build, deploy, and monetize autonomous agents, no cloud required." -> "AI assistant that drafts your email, schedules your meetings, and sends your follow-ups. Runs on your computer; every action waits for your tap." |
| src/sections/CloudVsLocal.tsx | Homepage column subhead | "Local-first, your infrastructure" -> "Runs on your computer" |
| app/(auth)/login/page.tsx | Login footer pill row | "Local-first / Privacy-first / On-chain" -> "Your computer / Encrypted / Signed receipts" |
| app/(auth)/signup/page.tsx | Signup footer pill row | "Local-first / Privacy-first / Open source" -> "Your computer / Encrypted / Open source" |

The JSON-LD fix is the most impactful, that's what Google reads to
generate the search-result snippet. Replacing "DeveloperApplication"
with "ProductivityApplication" in the same blob also matches the
audience the rest of the site now targets.

Editorial blog content (`app/blog/[id]/page.tsx`) stays unchanged,
that's the writer's voice describing past decisions, not marketing
claims. Same policy as #153.

The slug `'local-first-threat-model'` in `app/blog/page.tsx` stays
since it's a URL identifier; renaming would 404 any inbound link.

## Verified

- pnpm exec tsc --noEmit: clean
- pnpm check: 3 passed, 0 failed
- grep "Local-first" outside app/blog returns 0 hits

## Rollback

Single git revert. 4 files.
operatoruplift added a commit that referenced this pull request Apr 28, 2026
PR #168 retired the "Commander" default in /api/auth/signup. PR #186
retired it in /settings page. But four more places still stamped
"Commander" on a fresh user's account:

| File | Surface |
|---|---|
| app/(auth)/signup/page.tsx:35 | localStorage 'user' write after Supabase signup |
| app/(auth)/login/page.tsx:60 | userName fallback after Privy login |
| app/(auth)/login/page.tsx:165 | localStorage 'user' write after wallet payment |
| app/(dashboard)/profile/page.tsx:11 | initial useState for the profile page |
| app/(dashboard)/onboarding/page.tsx:43 | onboarding's saved user.name |

Each now derives a default from the email's local part (jane@x.com
-> "jane") or falls back to "Friend" -- matching the pattern set in
#168.

The two comment hits left in the repo (chat/page.tsx + the
auth/signup route) explicitly DOCUMENT what was retired and stay.

After this merges:
  grep -rnE "'Commander'" app/ src/
returns zero non-comment hits.

## Verified

- pnpm exec tsc --noEmit: clean
- pnpm check: 3 passed, 0 failed
- Banned-vocab grep: 0 user-facing hits

## Rollback

Single git revert. 4 files.
operatoruplift added a commit that referenced this pull request Apr 28, 2026
… pages (#192)

Two new specs added to consumer-copy.spec.ts so the post-#190/#191
state can't drift back.

## "JSON-LD structured data uses the consumer pitch"

PR #190 rewrote the schema.org SoftwareApplication description blob
that Google reads for rich-result snippets. The old text was:
"Local-first AI agent platform with secure, private memory. Build,
deploy, and monetize autonomous agents, no cloud required."

Now the test:
- Asserts the new "drafts your email" pitch IS in the JSON-LD
- Asserts the old "Local-first AI agent platform" + "autonomous
  agents" strings are NOT

## "/login + /signup auth pages do not show 'Commander'"

PRs #168, #186, and #191 retired "Commander" across the API + 5
client surfaces. The auth pages are the funnel where a fresh user
landed - this spec verifies neither /login nor /signup ever shows
the word, and also verifies "Local-first" stays out (the auth
footer pill rows used to say it; #190 fixed that).

## Verified

- pnpm exec tsc --noEmit: clean
- pnpm exec playwright test consumer-copy.spec.ts: 8 passed (37.3s)

## Rollback

Single git revert. One file.
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