@biffo/cli 0.244.8 → 0.244.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,65 @@
1
+ name: 'CodeQL'
2
+
3
+ on:
4
+ push:
5
+ branches: [dev, staging, main]
6
+ pull_request:
7
+ branches: [dev, staging, main]
8
+ schedule:
9
+ # Weekly catch-up scan (Tuesday 05:17 UTC) for issues that land outside
10
+ # PR review (e.g. direct merges onto a branch).
11
+ - cron: '17 5 * * 2'
12
+
13
+ jobs:
14
+ analyze:
15
+ name: Analyze (${{ matrix.language }})
16
+ runs-on: ${{ vars.RUNNER_LABEL || 'ubuntu-latest' }}
17
+ # CodeQL code scanning requires GitHub Advanced Security (GHAS) on private
18
+ # repos — the analysis runs but the SARIF upload fails without it. So this
19
+ # is opt-in: enable GHAS on the repo, then set the repo variable
20
+ # ENABLE_CODE_SCANNING=true. Left dormant (not failing) otherwise.
21
+ # See biffo-template's codeql.yml for the full reasoning (#1214): a public
22
+ # repo can scan for free, so it does; a private one still needs the opt-in.
23
+ # Both existing plugin repos are public, so this scans them for nothing —
24
+ # which is exactly why their never having been scanned was worth fixing
25
+ # (#1224).
26
+ if: github.event.repository.private == false || vars.ENABLE_CODE_SCANNING == 'true'
27
+ timeout-minutes: 15
28
+ permissions:
29
+ # Required for CodeQL to upload SARIF results.
30
+ security-events: write
31
+ contents: read
32
+ actions: read
33
+
34
+ strategy:
35
+ fail-fast: false
36
+ matrix:
37
+ include:
38
+ - language: javascript-typescript
39
+ build-mode: none
40
+ - language: python
41
+ build-mode: none
42
+
43
+ steps:
44
+ - name: Checkout repository
45
+ uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
46
+
47
+ - name: Initialize CodeQL
48
+ uses: github/codeql-action/init@v4
49
+ with:
50
+ languages: ${{ matrix.language }}
51
+ build-mode: ${{ matrix.build-mode }}
52
+ queries: security-extended
53
+
54
+ # autobuild intentionally omitted (build-mode 'none'):
55
+ # - the plugin's Python (src/, tests/) has no build step CodeQL needs.
56
+ # - javascript-typescript is declared even though a fresh plugin ships no
57
+ # web/ directory: the skeleton itself carries scripts/*.mjs, and every
58
+ # real plugin grows web/ and web-admin/ (both existing ones have them).
59
+ # Declaring it only once a plugin gains a frontend would mean the scan
60
+ # silently covers less than it appears to — the shape #1270 records for
61
+ # the dependency audits.
62
+ - name: Perform CodeQL Analysis
63
+ uses: github/codeql-action/analyze@v4
64
+ with:
65
+ category: '/language:${{ matrix.language }}'
@@ -34,9 +34,10 @@ anywhere in `services/api/`, on purpose.
34
34
 
35
35
  ```
36
36
  apps/frontend/ # Next.js 15 static export. `/` is the SSO demo ("<name> - Hello <username>",
37
- # proving the shared-session SSO works); src/lib/auth-gate.tsx + the
38
- # src/app/example/ routes show the public-default / opt-in-auth pattern
39
- # ("Your app goes here" below). src/lib/auth.ts reads the shared session.
37
+ # proving the shared-session SSO works end to end, gate included);
38
+ # src/lib/auth-gate.tsx is the reusable wrapper for any OTHER page that
39
+ # needs the same gate ("Your app goes here" below). src/lib/auth.ts reads
40
+ # the shared session.
40
41
  services/api/ # FastAPI + Mangum backend. Verifies the core project's Cognito JWT itself
41
42
  # (defense in depth — API Gateway's own JWT authorizer is the first layer).
42
43
  # core_client.py is the ONLY sanctioned way to reach core-owned data.
@@ -81,12 +82,10 @@ else depends on it.
81
82
  This is a Next.js **App Router** app with `output: 'export'` (a static site).
82
83
  A route is just a folder with a `page.tsx` under `apps/frontend/src/app/`:
83
84
 
84
- | File | URL served |
85
- | ------------------------------- | ----------------------------------- |
86
- | `src/app/page.tsx` | `/` (the demo — replace or keep) |
87
- | `src/app/pricing/page.tsx` | `/pricing/` |
88
- | `src/app/example/page.tsx` | `/example/` (public example, below) |
89
- | `src/app/example/members/page.tsx` | `/example/members/` (gated example) |
85
+ | File | URL served |
86
+ | --------------------------- | --------------------------------- |
87
+ | `src/app/page.tsx` | `/` (the demo — replace or keep) |
88
+ | `src/app/pricing/page.tsx` | `/pricing/` |
90
89
 
91
90
  **The `basePath` / `PATH_PREFIX` wiring is automatic — don't hand-write it.**
92
91
  The core project's CloudFront routes `baseurl.com/<name>/*` to this sibling and
@@ -116,8 +115,7 @@ browser never holds a core credential.
116
115
 
117
116
  The go-live state for most products is a **public** app. That is the easy path
118
117
  here: any `page.tsx` you add is served **unauthenticated** the moment it
119
- deploys — no auth code, no bounce. `src/app/example/page.tsx` is a one-screen
120
- demonstration of exactly that; copy it or delete it.
118
+ deploys — no auth code, no bounce, nothing to opt out of.
121
119
 
122
120
  When a page _does_ need a signed-in user, opt in with the `<AuthGate>` helper
123
121
  (`src/lib/auth-gate.tsx`) — one wrapper, and only that page becomes private:
@@ -142,15 +140,18 @@ export default function Dashboard() {
142
140
  A signed-out visitor is redirected to the core portal's login and returned to
143
141
  that exact route afterwards; a signed-in visitor sees the content. `AuthGate`
144
142
  builds on `getCurrentSession`/`auth.ts` and never signs anyone in itself
145
- (ADR-0007). `src/app/example/members/page.tsx` is the runnable version of the
146
- snippet above. Wrap only what must be private — never gate the whole app.
143
+ (ADR-0007) it is the same round-trip `/` already runs, packaged as a
144
+ one-line wrapper for any page besides `/`. Wrap only what must be private —
145
+ never gate the whole app. There is no separate demo route for this: `/`
146
+ already proves the mechanism works end to end, and the snippet above is the
147
+ runnable form.
147
148
 
148
149
  ### The path a founder actually walks
149
150
 
150
151
  1. Run locally (`pnpm dev`, below) and open `/` — watch the SSO demo work.
151
152
  2. Replace `src/app/page.tsx` with your own public home page (or add
152
153
  `src/app/<something>/page.tsx`). It's public by default — that's your
153
- go-live state. Delete the `example/` routes once you've read them.
154
+ go-live state.
154
155
  3. For any area that needs a login, wrap its `page.tsx` in `<AuthGate>`.
155
156
  4. Push to `main`; `deploy.yml` builds the static export with the right
156
157
  `NEXT_PUBLIC_BASE_PATH` and syncs it to S3 behind the core CloudFront —
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@biffo/cli",
3
- "version": "0.244.8",
3
+ "version": "0.244.10",
4
4
  "description": "Biffo project scaffolding CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,31 +0,0 @@
1
- 'use client'
2
-
3
- import { AuthGate } from '@/lib/auth-gate'
4
-
5
- // The SAME page, made private by a single wrapper. Opting into auth is one
6
- // deliberate line — <AuthGate> — not the default. A signed-out visitor is
7
- // bounced to the core portal's login (ADR-0007) and returned here afterwards;
8
- // a signed-in visitor sees the content below.
9
- //
10
- // The render-prop form hands you the session, whose ID token you pass to THIS
11
- // sibling's own backend via createApiClient (never the core API directly,
12
- // ADR-0002). This example doesn't call the backend, but shows where the token
13
- // comes from.
14
- export default function ExampleMembersPage() {
15
- return (
16
- <AuthGate>
17
- {(session) => (
18
- <main className="center-screen">
19
- <div>
20
- <h1>Members only</h1>
21
- <p>You&apos;re signed in — this rendered because a valid session exists.</p>
22
- <p>
23
- Your ID token (for calls to this sibling&apos;s backend) is{' '}
24
- {session.getIdToken().getJwtToken().slice(0, 8)}…
25
- </p>
26
- </div>
27
- </main>
28
- )}
29
- </AuthGate>
30
- )
31
- }
@@ -1,24 +0,0 @@
1
- import Link from 'next/link'
2
-
3
- // A minimal PUBLIC page — the go-live default.
4
- //
5
- // There is no auth code here, and that is the whole point: anything you drop
6
- // under src/app/ is served unauthenticated the moment it deploys. Delete this
7
- // route once you've seen how it works, or copy it as the starting point for
8
- // your own public content. To make a page private instead, wrap it in
9
- // <AuthGate> — see ./members/page.tsx.
10
- export default function ExamplePublicPage() {
11
- return (
12
- <main className="center-screen">
13
- <div>
14
- <h1>This page is public</h1>
15
- <p>
16
- Anyone can see it — no login, no redirect. This is how most of your app ships at go-live.
17
- </p>
18
- <p>
19
- <Link href="/example/members/">See the same pattern, but auth-gated →</Link>
20
- </p>
21
- </div>
22
- </main>
23
- )
24
- }