Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
3433d51
f3 me initial
taterhead247 Mar 3, 2026
1c0951c
it's alive!
taterhead247 Mar 5, 2026
9ca8017
mostly working local
taterhead247 Mar 5, 2026
0d90e53
branding
taterhead247 Mar 5, 2026
d6fb848
fixing ci checks
taterhead247 Mar 5, 2026
1b80430
fix build by downgrading react to 18
taterhead247 Mar 5, 2026
deba197
fixed orange change bar
taterhead247 Mar 5, 2026
2e1dc1e
remove gif as allowable type
taterhead247 Mar 5, 2026
5a142fd
Fix bugs in roles API, avatar state, toast a11y, meta serialization, …
Copilot Mar 5, 2026
45e1458
saving seed file
taterhead247 Mar 6, 2026
3e87bd2
converted from firebase to cloud run
taterhead247 Mar 12, 2026
8e4f87d
more
taterhead247 Mar 12, 2026
909f4bf
2 artifact registries instead of 1
taterhead247 Mar 12, 2026
72bec82
docker fixes for deploy
taterhead247 Mar 12, 2026
a2324bf
still fixing docker - adding turbo
taterhead247 Mar 12, 2026
c99c84e
docker fix. moving env variable
taterhead247 Mar 12, 2026
cc76bbe
docker - removed node_env
taterhead247 Mar 12, 2026
e27ceb9
docker fixes. dependencies
taterhead247 Mar 12, 2026
58b6d66
fixed a few console errors
taterhead247 Mar 12, 2026
2ab375a
minor html complaint
taterhead247 Mar 12, 2026
d034174
Fix input validation, type safety, and missing config files in apps/m…
Copilot Mar 13, 2026
6e438fa
removed firebase residue and cleanup
taterhead247 Mar 13, 2026
0560373
matching versions and removing gifs
taterhead247 Mar 13, 2026
47cd123
open-redirect vector
taterhead247 Mar 13, 2026
02a21a0
useful auth fail responses
taterhead247 Mar 13, 2026
057ae68
consolidate references
taterhead247 Mar 13, 2026
ca3eef5
html fix
taterhead247 Mar 13, 2026
c6dd468
toast timers
taterhead247 Mar 13, 2026
60e8b60
add server-only package and improve environment variable handling
taterhead247 Mar 13, 2026
9e61ad4
handling server side security changes
taterhead247 Mar 13, 2026
00d9643
type validation
taterhead247 Mar 13, 2026
81a3097
meta validaton
taterhead247 Mar 13, 2026
f8cccd7
wasn't saved yet
taterhead247 Mar 13, 2026
a92b791
new api
taterhead247 Mar 15, 2026
abb60e4
missed some
taterhead247 Mar 15, 2026
df04672
a ton of changes on user reckoning
taterhead247 Mar 15, 2026
87bdccf
stopping to take a look at api security
taterhead247 Mar 16, 2026
3b0ca35
vitest fix
taterhead247 Apr 5, 2026
f1ece7e
lint cleanup
taterhead247 Apr 5, 2026
3da429d
that last one was dev, now it's to make lefthook happy
taterhead247 Apr 9, 2026
c8549c0
Refactor me app to use @acme/sso SDK and fix sign-out flow
taterhead247 Apr 9, 2026
85e5894
fix(me): Security fixes, hook extraction, dead code removal (#235)
pstaylor-patrick Apr 9, 2026
00a90bd
Add me app to env generation pipeline and update dev setup docs
pstaylor-patrick Apr 9, 2026
24ba58a
Merge branch 'dev' into feat/me
taterhead247 Apr 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 71 additions & 15 deletions .claude/commands/dev-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ After install, re-verify. If still missing, print the manual install instruction

---

## Step 3 — Check GCP Authentication
## Step 3 — Check GCP Authentication and Project Context

```bash
gcloud auth print-identity-token 2>/dev/null
Expand All @@ -62,19 +62,64 @@ GCP authentication needed. Run these commands in your terminal:

Wait for the user to confirm, then re-check.

**Quota project check:**

The ADC quota project must be set correctly for the Cloud SQL proxy and secret access to work. This is critical when switching between workspaces (e.g., f3-nation vs joinfold).
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is joinfold?


```bash
QUOTA_PROJECT=$(cat ~/.config/gcloud/application_default_credentials.json 2>/dev/null | node -e "const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));console.log(d.quota_project_id||'')" 2>/dev/null)
```

If `QUOTA_PROJECT` is not `f3-authentication-staging`, fix it:

```bash
gcloud auth application-default set-quota-project f3-authentication-staging
```

After changing the quota project, restart the Cloud SQL proxy (kill existing process; launchd or systemd will restart it automatically):

```bash
kill $(lsof -ti :5433) 2>/dev/null
# Wait for launchd/systemd to restart it
sleep 2
lsof -i :5433 # verify new process is listening
```

**GCP project access verification:**

The monorepo uses two GCP projects for secrets:

| Project | Apps | Secrets |
| --------------------------- | -------------- | ----------------------------------------------------------------- |
| `f3-authentication-staging` | api, map, auth | DB creds, API keys, auth JWT, GCS logo bucket, SendGrid |
| `f3-me-app-staging` | me | OAuth client secret, session secret, F3 API key, GCS avatar creds |

Verify access to both:

```bash
gcloud secrets list --project=f3-authentication-staging --limit=1 2>/dev/null
gcloud secrets list --project=f3-me-app-staging --limit=1 2>/dev/null
```

If the second fails, warn: "No access to f3-me-app-staging secrets. The me app .env.local won't be auto-generated. Ask a project owner (tackle@f3nation.com) for Secret Manager Secret Accessor role."

---

## Step 4 — Generate Environment

Check if `.env` exists at the repo root:
Check if `.env` and me app env exist:

```bash
test -f .env && echo "EXISTS" || echo "MISSING"
test -f .env && echo ".env EXISTS" || echo ".env MISSING"
test -f apps/me/.env.local && echo "me .env.local EXISTS" || echo "me .env.local MISSING"
```

**If missing or `reset` mode:** Run `pnpm env:generate` to pull staging secrets from GCP and create `.env` with symlinks.
**If either is missing or `reset` mode:** Run `pnpm env:generate` to pull staging secrets from GCP. This will:

**If exists:** Validate it has the required variables by cross-referencing with `packages/env/src/index.ts`. Report any missing vars.
- Create root `.env` from `f3-authentication-staging` secrets (shared by api, map, auth via symlinks)
- Create `apps/me/.env.local` from `f3-me-app-staging` secrets (me app has its own OAuth client, session, and GCS config)

**If both exist:** Validate required variables. The root `.env` should have: `DATABASE_URL`, `API_KEY`, `AUTH_SECRET`, `AUTH_JWT_PRIVATE_KEY`. The me `.env.local` should have: `OAUTH_CLIENT_ID`, `OAUTH_CLIENT_SECRET`, `SESSION_SECRET`, `F3_API_KEY`, `F3_API_BASE_URL`.

---

Expand Down Expand Up @@ -154,10 +199,16 @@ Prerequisites:
GCP Auth:
Identity: ✓ (user@example.com)
App Default: ✓
ADC Quota Project: f3-authentication-staging ✓

GCP Projects:
f3-authentication-staging: ✓ (secrets accessible)
f3-me-app-staging: ✓ (secrets accessible)

Environment:
.env: ✓ (generated 2026-04-09)
Symlinks: api ✓ map ✓ auth ✓
me .env.local: ✓ (generated 2026-04-09, from f3-me-app-staging)

Database:
Proxy: ✓ running on :5433 (background daemon)
Expand All @@ -179,18 +230,23 @@ When called with `fix`, diagnose and auto-fix issues:

1. Missing prerequisites → install them
2. GCP auth expired → prompt re-auth
3. `.env` missing or incomplete → regenerate
4. Proxy not running → start it (or install daemon)
5. Port conflicts → identify and offer to kill conflicting processes
6. Stale symlinks → recreate
3. ADC quota project wrong → `gcloud auth application-default set-quota-project f3-authentication-staging` + restart proxy
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is ADC? Sorry if I'm missing something

4. `.env` missing or incomplete → regenerate via `pnpm env:generate`
5. `apps/me/.env.local` missing → regenerate (requires `f3-me-app-staging` access)
6. Proxy not running → start it (or install daemon)
7. Port conflicts → identify and offer to kill conflicting processes
8. Stale symlinks → recreate

---

## Error Handling

| Condition | Action |
| -------------------- | ---------------------------------------------------------- |
| No GCP access | Print instructions to request access from team lead |
| Proxy port conflict | Identify process, offer to kill or suggest alternate port |
| DB connection failed | Check proxy → check credentials → check DATABASE_URL |
| App won't start | Check port conflicts, missing env vars, pending migrations |
| Condition | Action |
| --------------------------- | --------------------------------------------------------------------------------------------------- |
| No GCP access | Print instructions to request access from team lead |
| Wrong ADC quota project | Run `gcloud auth application-default set-quota-project f3-authentication-staging` and restart proxy |
| Proxy port conflict | Identify process, offer to kill or suggest alternate port |
| DB connection reset | Likely wrong ADC quota project — fix and restart proxy |
| DB connection failed | Check proxy → check credentials → check DATABASE_URL |
| No f3-me-app-staging access | Warn, skip me .env.local generation, suggest requesting access from tackle@f3nation.com |
| App won't start | Check port conflicts, missing env vars, pending migrations |
140 changes: 140 additions & 0 deletions .github/workflows/deploy-me.yml
Comment thread
taterhead247 marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
name: Deploy f3-me

on:
push:
tags:
- "me@*"

# Prevent concurrent deploys of the same tag
concurrency:
group: deploy-me-${{ github.ref_name }}
cancel-in-progress: false

env:
IMAGE_NAME: f3-me
STAGING_PROJECT: f3-me-app-staging
PROD_PROJECT: f3-me-app
REGION: us-east1
SERVICE_NAME: f3-me
AR_REPO: cloud-run-builds

jobs:
# ── Gate: wait for CI to pass on this commit ──
ci-check:
runs-on: ubuntu-latest
steps:
- name: Wait for CI to pass
uses: lewagon/wait-on-check-action@v1.3.4
with:
ref: ${{ github.sha }}
repo-token: ${{ secrets.GITHUB_TOKEN }}
check-name: "test-coverage"
wait-interval: 15
allowed-conclusions: success

# ── Build container image (once) ──
build:
needs: ci-check
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
outputs:
image: ${{ steps.meta.outputs.image }}
steps:
- uses: actions/checkout@v4

- name: Authenticate to GCP (staging project for AR)
uses: google-github-actions/auth@v2
with:
workload_identity_provider: ${{ secrets.ME_WIF_PROVIDER }}
service_account: ${{ secrets.ME_WIF_SA_STAGING }}

- name: Set up Cloud SDK
uses: google-github-actions/setup-gcloud@v2

- name: Authorize Docker to Artifact Registry
run: gcloud auth configure-docker ${{ env.REGION }}-docker.pkg.dev --quiet

- name: Extract tag version
id: meta
run: |
TAG="${GITHUB_REF_NAME}" # e.g. me@1.2.3
VERSION="${TAG#me@}" # e.g. 1.2.3
IMAGE="${REGION}-docker.pkg.dev/${STAGING_PROJECT}/${AR_REPO}/${IMAGE_NAME}:${VERSION}"
echo "image=${IMAGE}" >> "$GITHUB_OUTPUT"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"

- name: Build and push Docker image
run: |
docker build \
--file apps/me/Dockerfile \
--tag "${{ steps.meta.outputs.image }}" \
.
docker push "${{ steps.meta.outputs.image }}"

# ── Deploy to staging ──
deploy-staging:
needs: build
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
environment:
name: me-staging
url: https://staging.me.f3nation.com
steps:
- name: Authenticate to GCP (staging)
uses: google-github-actions/auth@v2
with:
workload_identity_provider: ${{ secrets.ME_WIF_PROVIDER }}
service_account: ${{ secrets.ME_WIF_SA_STAGING }}

- name: Deploy to Cloud Run (staging)
uses: google-github-actions/deploy-cloudrun@v2
with:
service: ${{ env.SERVICE_NAME }}
image: ${{ needs.build.outputs.image }}
region: ${{ env.REGION }}
project_id: ${{ env.STAGING_PROJECT }}
# Env vars are set via Cloud Run secrets / env config (see scripts/cloud-run-env.sh)

# ── Deploy to production (requires approval) ──
deploy-prod:
needs: [build, deploy-staging]
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
environment:
name: me-production
url: https://me.f3nation.com
steps:
- name: Authenticate to GCP (prod)
uses: google-github-actions/auth@v2
with:
workload_identity_provider: ${{ secrets.ME_WIF_PROVIDER }}
service_account: ${{ secrets.ME_WIF_SA_PROD }}

- name: Set up Cloud SDK
uses: google-github-actions/setup-gcloud@v2

- name: Authorize Docker to Artifact Registry
run: gcloud auth configure-docker ${{ env.REGION }}-docker.pkg.dev --quiet

- name: Promote image to prod Artifact Registry
run: |
STAGING_IMAGE="${{ needs.build.outputs.image }}"
PROD_IMAGE="${REGION}-docker.pkg.dev/${PROD_PROJECT}/${AR_REPO}/${IMAGE_NAME}:${STAGING_IMAGE##*:}"
docker pull "${STAGING_IMAGE}"
docker tag "${STAGING_IMAGE}" "${PROD_IMAGE}"
docker push "${PROD_IMAGE}"
echo "prod_image=${PROD_IMAGE}" >> "$GITHUB_ENV"

- name: Deploy to Cloud Run (prod)
uses: google-github-actions/deploy-cloudrun@v2
with:
service: ${{ env.SERVICE_NAME }}
image: ${{ env.prod_image }}
region: ${{ env.REGION }}
project_id: ${{ env.PROD_PROJECT }}
9 changes: 9 additions & 0 deletions apps/api/src/app/docs/openapi.json/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ As of February 1, 2026, regional admins can only create read-only API keys. If y
"event-tag",
"attendance",
"location",
"me",
"org",
"ping",
"position",
Expand All @@ -153,6 +154,10 @@ As of February 1, 2026, regional admins can only create read-only API keys. If y
name: "Org Chart",
tags: ["Org Chart"],
},
{
name: "Me",
tags: ["Me"],
},
],
tags: [
{
Expand All @@ -174,6 +179,10 @@ As of February 1, 2026, regional admins can only create read-only API keys. If y
name: "location",
description: "Physical location management for workouts",
},
{
name: "Me",
description: "Used by the F3 Me app",
},
{
name: "org",
description: "Organization management (regions, AOs, etc.)",
Expand Down
12 changes: 12 additions & 0 deletions apps/me/.env.cloud-run.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Cloud Run deployment secrets — populate and run scripts/cloud-run-env.sh
# Copy to .env.cloud-run.prod or .env.cloud-run.staging and fill in values.

OAUTH_CLIENT_ID=
OAUTH_CLIENT_SECRET=
OAUTH_REDIRECT_URI=
SESSION_SECRET=
F3_API_KEY=
F3_API_BASE_URL=
GCS_BUCKET=
GCS_CREDENTIALS=
NEXT_PUBLIC_SITE_URL=
28 changes: 28 additions & 0 deletions apps/me/.env.local.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# =============================================================================
# F3 Me — Local Development Environment (example)
# =============================================================================
# Don't edit this file directly. Run `pnpm env:generate` to auto-generate
# apps/me/.env.local from GCP Secret Manager (project: f3-me-app-staging).
#
# If you need manual setup, copy this file to .env.local and fill in values.

# Auth (F3 SSO — points to local auth server on :3004)
OAUTH_CLIENT_ID=f3-me-local
OAUTH_CLIENT_SECRET=<from-gcp: f3-me-app-staging/oauth-client-secret>
OAUTH_REDIRECT_URI=http://localhost:3003/api/auth/callback
AUTH_PROVIDER_URL=http://localhost:3004

# Session
SESSION_SECRET=<from-gcp: f3-me-app-staging/session-secret>

# F3 Nation API (local API on :3001)
F3_API_KEY=<from-gcp: f3-me-app-staging/f3-api-key>
F3_API_BASE_URL=http://localhost:3001/v1

# Google Cloud Storage (avatar uploads)
GCS_BUCKET=f3-public-images-staging
GCS_CREDENTIALS=<from-gcp: f3-me-app-staging/gcs-credentials>

# App
NEXT_PUBLIC_SITE_URL=http://localhost:3003
NODE_ENV=development
Loading
Loading