@payez/next-mvp 4.14.0 → 4.15.0
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.
- package/CHANGELOG.md +23 -0
- package/dist/api-handlers/mfa/totp-confirm.d.ts +1 -1
- package/dist/api-handlers/mfa/totp-confirm.js +10 -6
- package/dist/api-handlers/test/force-expire.d.ts +4 -5
- package/dist/api-handlers/test/force-expire.js +14 -63
- package/dist/auth/better-auth.d.ts +16 -0
- package/dist/auth/better-auth.js +34 -0
- package/dist/lib/idp-client-config.js +1 -1
- package/dist/lib/log-safe.d.ts +6 -0
- package/dist/lib/log-safe.js +9 -0
- package/dist/lib/payez-client-secret.js +2 -1
- package/dist/lib/token-pages-switch.d.ts +23 -0
- package/dist/lib/token-pages-switch.js +48 -0
- package/dist/pages/test-env/JwtInspectPage.d.ts +16 -14
- package/dist/pages/test-env/JwtInspectPage.js +16 -14
- package/dist/pages/test-env/RefreshTokenPage.d.ts +7 -10
- package/dist/pages/test-env/RefreshTokenPage.js +7 -10
- package/dist/pages/test-env/guarded.js +21 -57
- package/dist/pages/test-env/index.d.ts +15 -24
- package/dist/pages/test-env/index.js +15 -26
- package/package.json +11 -1
- package/src/api-handlers/mfa/totp-confirm.ts +13 -5
- package/src/api-handlers/test/force-expire.ts +13 -70
- package/src/auth/better-auth.ts +44 -2
- package/src/lib/idp-client-config.ts +2 -2
- package/src/lib/log-safe.ts +9 -0
- package/src/lib/payez-client-secret.ts +2 -1
- package/src/lib/token-pages-switch.ts +44 -0
- package/src/pages/test-env/JwtInspectPage.tsx +16 -14
- package/src/pages/test-env/RefreshTokenPage.tsx +7 -10
- package/src/pages/test-env/guarded.tsx +21 -55
- package/src/pages/test-env/index.ts +15 -26
|
@@ -14,25 +14,22 @@ import { redactCredentials } from './redact-credentials';
|
|
|
14
14
|
* `/api/test/force-expire`. That endpoint MUTATES SESSION STATE.
|
|
15
15
|
*
|
|
16
16
|
* ────────────────────────── WHY THIS WARNING EXISTS (QAPert 35000) ──────────────────────────
|
|
17
|
-
* The force-expire HANDLER was fixed (244877
|
|
18
|
-
*
|
|
19
|
-
* covered the ROUTE AND NOT THE PAGE THAT DRIVES IT. This page is a separate
|
|
17
|
+
* The force-expire HANDLER was fixed (244877) and its docstring corrected to
|
|
18
|
+
* say so — but that fix covered the ROUTE AND NOT THE PAGE THAT DRIVES IT. This page is a separate
|
|
20
19
|
* public export carrying its own mount instructions, so a consumer can follow
|
|
21
20
|
* these lines and never once read the handler's warning.
|
|
22
21
|
*
|
|
23
|
-
* THIS PAGE HAS NO ENV GATE OF ITS OWN
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* setting that flag anywhere this page is also reachable.
|
|
22
|
+
* THIS PAGE HAS NO ENV GATE OF ITS OWN, and since PAY-3216 neither has the
|
|
23
|
+
* handler it drives: mounting is the gate. Wherever this page and the
|
|
24
|
+
* force-expire route are both mounted, the button works.
|
|
27
25
|
*
|
|
28
26
|
* ────────────────────────── IF YOU MOUNT IT, MOUNT IT LIKE THIS ──────────────────────────
|
|
29
27
|
* ```typescript
|
|
30
28
|
* // app/test-env/refresh-token/page.tsx — TEST/DEV ENVIRONMENTS ONLY
|
|
31
29
|
* export { RefreshTokenPage as default } from '@payez/next-mvp/pages/test-env';
|
|
32
30
|
* ```
|
|
33
|
-
*
|
|
34
|
-
* do
|
|
35
|
-
* refresh flow, DO NOT MOUNT THIS AT ALL.
|
|
31
|
+
* The button needs /api/test/force-expire mounted too; there is no flag. If
|
|
32
|
+
* you do not need to exercise the refresh flow, DO NOT MOUNT THIS AT ALL.
|
|
36
33
|
*/
|
|
37
34
|
export function RefreshTokenPage() {
|
|
38
35
|
const { data: session } = authClient.useSession();
|
|
@@ -1,81 +1,47 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* ruling 35321). These are what `@payez/next-mvp/pages/test-env` exports. The
|
|
4
|
-
* raw client components are NOT exported.
|
|
2
|
+
* The BARREL that `@payez/next-mvp/pages/test-env` exports: one server-component wrapper per test-env page.
|
|
5
3
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* that should not have happened. It is NOT a licence to mount these freely:
|
|
9
|
-
* setting ENABLE_TEST_ROUTES=true in an environment where these pages are
|
|
10
|
-
* mounted gives you exactly the exposure this package spent 248991 documenting
|
|
11
|
-
* - a live session token and a copy button. If you are not actively debugging,
|
|
12
|
-
* DO NOT MOUNT THESE AT ALL. The safest configuration remains their absence.
|
|
4
|
+
* PAY-3216 (Jon's order, 15 Nov): the ENABLE_TEST_ROUTES check and its notFound() are REMOVED. Each wrapper renders
|
|
5
|
+
* its page unconditionally, as the pages rendered before 1d40a8c. Ruling 35321 is withdrawn.
|
|
13
6
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* NEXT_PUBLIC_ environment variables are only available in the Node.js
|
|
19
|
-
* environment"). A check written inside those files would read `undefined` on
|
|
20
|
-
* the client and deny ALWAYS - killing the tool in dev too - while reading the
|
|
21
|
-
* REAL value during SSR, producing a hydration mismatch. It would look like a
|
|
22
|
-
* gate, satisfy a grep for one, and protect nothing.
|
|
7
|
+
* PAY-3220 (ruled Win 105653 s1): the ONE production switch, PAYEZ_TOKEN_PAGES_OFF (../../lib/token-pages-switch), sits
|
|
8
|
+
* here for the two token-showing pages ONLY. Unset, they render exactly as before. Set, they answer notFound(): a real
|
|
9
|
+
* 404, indistinguishable from a route that was never registered (a 403 would confirm the page exists).
|
|
10
|
+
* TestEnvPage (the index) and EmergencyLogoutPage are NOT covered, on purpose: Jon named the two token-showing pages.
|
|
23
11
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* The test is `=== 'true'`, not truthiness. Unset, empty, "false", "0", "TRUE"
|
|
29
|
-
* and every typo all deny. The UNSAFE state requires a deliberate, exact act;
|
|
30
|
-
* the SAFE state is what you get by doing nothing, including by misconfiguring
|
|
31
|
-
* it. A gate whose default is "open" is not a gate.
|
|
32
|
-
*
|
|
33
|
-
* `notFound()` is deliberate and is not a 403: a real 404 is indistinguishable
|
|
34
|
-
* from a route that was never registered, whereas a 403 CONFIRMS the page
|
|
35
|
-
* exists to anyone who probes for it. That is the same disclosure axis card
|
|
36
|
-
* 245920 was raised about, so shipping the confirming variant here would
|
|
37
|
-
* reintroduce next door the thing being fixed there.
|
|
38
|
-
*
|
|
39
|
-
* notFound() throws (NEXT_HTTP_ERROR_FALLBACK;404) and terminates rendering of
|
|
40
|
-
* the segment, so nothing below it runs and the client component is never sent
|
|
41
|
-
* to the browser. It does not need `return` - it is typed `never`.
|
|
12
|
+
* PER REQUEST: unstable_noStore() makes the segment dynamic, so a consumer's page is never prerendered with the build
|
|
13
|
+
* host's value. It is synchronous (the wrappers stay plain components, so PAY-3216's renderToString rows still hold) and
|
|
14
|
+
* a no-op outside a request. LIMIT: in Next 16 with cacheComponents (Dynamic I/O) it is a no-op too; the production
|
|
15
|
+
* roll's served check (both pages read back as 404 by request) is the row that would show it.
|
|
42
16
|
*/
|
|
43
17
|
import { notFound } from 'next/navigation';
|
|
44
|
-
|
|
18
|
+
import { unstable_noStore as noStore } from 'next/cache';
|
|
19
|
+
import { tokenPagesOff } from '../../lib/token-pages-switch';
|
|
45
20
|
import { TestEnvPage as TestEnvPageUnguarded } from './TestEnvPage';
|
|
46
21
|
import { JwtInspectPage as JwtInspectPageUnguarded } from './JwtInspectPage';
|
|
47
22
|
import { RefreshTokenPage as RefreshTokenPageUnguarded } from './RefreshTokenPage';
|
|
48
23
|
import { EmergencyLogoutPage as EmergencyLogoutPageUnguarded } from './EmergencyLogoutPage';
|
|
49
24
|
|
|
50
|
-
/**
|
|
51
|
-
* The single gate. Exact-match on purpose - see FAIL CLOSED above.
|
|
52
|
-
*
|
|
53
|
-
* Read at REQUEST time inside each page rather than once at module scope: a
|
|
54
|
-
* module-scope constant would be captured at build time, so a consumer who
|
|
55
|
-
* changed the variable would keep whatever value was baked into the bundle and
|
|
56
|
-
* would have no way to tell. Reading per render costs an object property
|
|
57
|
-
* lookup and removes an entire class of "I turned it off and it stayed on".
|
|
58
|
-
*/
|
|
59
|
-
function testRoutesEnabled(): boolean {
|
|
60
|
-
return process.env.ENABLE_TEST_ROUTES === 'true';
|
|
61
|
-
}
|
|
62
|
-
|
|
63
25
|
export function TestEnvPage() {
|
|
64
|
-
if (!testRoutesEnabled()) notFound();
|
|
65
26
|
return <TestEnvPageUnguarded />;
|
|
66
27
|
}
|
|
67
28
|
|
|
29
|
+
/** PAY-3220: per request, then the switch. notFound() throws, so nothing below it renders and no client code is sent. */
|
|
30
|
+
function refuseWhenTokenPagesOff(): void {
|
|
31
|
+
noStore();
|
|
32
|
+
if (tokenPagesOff()) notFound();
|
|
33
|
+
}
|
|
34
|
+
|
|
68
35
|
export function JwtInspectPage() {
|
|
69
|
-
|
|
36
|
+
refuseWhenTokenPagesOff();
|
|
70
37
|
return <JwtInspectPageUnguarded />;
|
|
71
38
|
}
|
|
72
39
|
|
|
73
40
|
export function RefreshTokenPage() {
|
|
74
|
-
|
|
41
|
+
refuseWhenTokenPagesOff();
|
|
75
42
|
return <RefreshTokenPageUnguarded />;
|
|
76
43
|
}
|
|
77
44
|
|
|
78
45
|
export function EmergencyLogoutPage() {
|
|
79
|
-
if (!testRoutesEnabled()) notFound();
|
|
80
46
|
return <EmergencyLogoutPageUnguarded />;
|
|
81
47
|
}
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* and the block below is a four-line copy-paste that mounts every debug page
|
|
8
8
|
* this package has. It previously carried no warning at all.
|
|
9
9
|
*
|
|
10
|
-
* NONE of these pages has an env gate of its own.
|
|
11
|
-
* handler (
|
|
10
|
+
* NONE of these pages has an env gate of its own. Like the force-expire
|
|
11
|
+
* handler (no flag since PAY-3216) and unlike the idp-token route
|
|
12
12
|
* (ENABLE_TOKEN_INSPECTOR), a mounted page is reachable exactly as far as your
|
|
13
13
|
* middleware allows. MOUNTING IS THE GATE — so gate the WHOLE /test-env
|
|
14
14
|
* segment, per environment, not page by page.
|
|
@@ -22,28 +22,19 @@
|
|
|
22
22
|
* RefreshTokenPage Drives the destructive /api/test/force-expire.
|
|
23
23
|
* EmergencyLogoutPage Mildest. Self-inflicted, recoverable.
|
|
24
24
|
*
|
|
25
|
-
* ──
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* is
|
|
25
|
+
* ── NO ENV GATE (PAY-3216, Jon's order, 15 Nov) ─────────────────────────────
|
|
26
|
+
* The ENABLE_TEST_ROUTES gate that 1d40a8c (4.2.0, ruling 35321) put on these
|
|
27
|
+
* four pages is REMOVED: they render with no flag set, as before that commit.
|
|
28
|
+
* The ruling is withdrawn. MOUNTING IS THE GATE: a mounted page is reachable
|
|
29
|
+
* exactly as far as your middleware allows. Which of them a production site
|
|
30
|
+
* mounts is the site owner's choice.
|
|
31
31
|
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* consumers add one env var to their dev environments and change no code.
|
|
39
|
-
*
|
|
40
|
-
* ── MOUNTING IS STILL THE PRIMARY GATE ──────────────────────────────────────
|
|
41
|
-
* Do not read the env var as making mounting safe. The wrapper is a backstop
|
|
42
|
-
* for a mount that should not have happened. With ENABLE_TEST_ROUTES=true in an
|
|
43
|
-
* environment where these are mounted you have exactly the exposure 248991
|
|
44
|
-
* documented: a live session token, one click from the clipboard. If you are
|
|
45
|
-
* not actively debugging, DO NOT MOUNT THESE AT ALL — the safest configuration
|
|
46
|
-
* is still their absence, and the env var does not change that.
|
|
32
|
+
* ── ONE PRODUCTION SWITCH (PAY-3220) ────────────────────────────────────────
|
|
33
|
+
* PAYEZ_TOKEN_PAGES_OFF, UNSET by default (every page works as above). Set on
|
|
34
|
+
* a production host, on Jon's word only, it makes JwtInspectPage,
|
|
35
|
+
* RefreshTokenPage and /api/test/force-expire answer 404. TestEnvPage and
|
|
36
|
+
* EmergencyLogoutPage are not covered. Read server-side per request; see
|
|
37
|
+
* lib/token-pages-switch for the values it accepts.
|
|
47
38
|
*
|
|
48
39
|
* Each page's own docstring carries the detail. If you are not actively
|
|
49
40
|
* debugging, DO NOT MOUNT THESE AT ALL — the safest configuration is their
|
|
@@ -65,9 +56,7 @@
|
|
|
65
56
|
* ```
|
|
66
57
|
*/
|
|
67
58
|
|
|
68
|
-
//
|
|
69
|
-
// etc. would reintroduce an ungated path to the same pages under a different
|
|
70
|
-
// import, which is the "opt-in gate nobody opts into" the ruling rejected.
|
|
59
|
+
// Through the barrel (./guarded), as on main: it is PAY-3220's seam. Since PAY-3216 it renders each page with no flag.
|
|
71
60
|
export {
|
|
72
61
|
TestEnvPage,
|
|
73
62
|
TestEnvPage as default,
|