Skip to content

Require server-issued CAPTCHA proof for authentication actions - #195

Merged
mvalancy merged 11 commits into
devfrom
fix/server-captcha-20261027
Oct 28, 2026
Merged

mvalancy merged 11 commits into
devfrom
fix/server-captcha-20261027

Conversation

@mvalancy

Copy link
Copy Markdown
Member

Core currently accepts arbitrary six-character CAPTCHA strings and lets direct GraphQL login/signup omit verification. This change requires server-issued, action-bound ALTCHA proof before protected authentication actions, with expiry, bounded issuance and atomic one-use redemption. Production rejects the old signing-key fallback; an unset key uses a random process-local key.

The sign-in/reset UI now obtains the server's proof, clears consumed/expired proof, and exposes accessible error/retry states. Core advertises its contract through /config; Cloud's existing contract remains separate. Auth-only GraphQL inputs accept proof too, and same-origin auth/challenge routes work through the development proxy and self-host nginx.

Fixes #183 after review and required validation. Part of #193. No provider account, dependency upgrade, shared library or deployment is introduced.

Validation so far (Node22.18.0/npm10.8.2, owned fixtures):

  • Negative baseline: ABC123 rejection test fails against the old verifier; retained.
  • Server:139/139 tests, including real HTTP GraphQL with native SQLite, missing/forged/wrong-action/replay negatives, valid login/signup, existing password limits and production startup.
  • Web:329/329 tests; types/build/lint passed before the final small focus refinement.
  • Built frontend through nginx + production API:4/4 headed tests, including direct REST negatives, real solved proof/login retry at390/1440px, and policy-failure keyboard recovery.
  • Existing signup delivery scenarios:10/10. Two focus tests exposed an initial-focus gap; a correction is included and its browser rerun is pending.
  • Independent exact-head review requested for b12ef2c1f0064ac7cc838ac1e806c52134a6802f; final composed checks/remote CI pending. Draft until resolved.

The new qc:captcha command requires an explicitly marked owned production-mode fixture and synthetic admin password. Traces remain private. The repo lesson records failures, commands, cause, correction and limits. Challenge ledger/rate limits are process-local; restart invalidates outstanding proof. This is proof-of-work abuse control, not human identity verification. Token purpose/OAuth/reset revocation remain #184; hosted parity and email delivery remain separate. Undici audit correction is tracked by #194 and is not folded into this auth change.

@github-actions

Copy link
Copy Markdown

🧪 Comprehensive Test Suite

  • Unit suites (Node 22.18.0 & 24.x) — core, web, server, mcp-server: ✅ passed
  • Installer & deploy config: ✅ passed

Full-stack smoke gate runs in the CI workflow.

@github-actions

Copy link
Copy Markdown

🧪 Comprehensive Test Suite

  • Unit suites (Node 22.18.0 & 24.x) — core, web, server, mcp-server: ✅ passed
  • Installer & deploy config: ✅ passed

Full-stack smoke gate runs in the CI workflow.

@mvalancy

Copy link
Copy Markdown
Member Author

Final correction head: 283a37549e02f633dfa47340372f47b72540ea00 (base ef495eff15ed7aac51e72dc7a1db1bb96d2b3695). Independent exact-head agent review found no remaining findings after these corrections:

  • Challenge throttling now uses the observed socket IP even with trust proxy=2; a real HTTP test rotates 31 forwarded headers and receives 429 on request 31.
  • Password submission is disabled and handler-guarded until required verification is ready. Loading, policy failure, expiry and consumed proof clear readiness; explicit optional development/legacy actions remain supported.
  • A successful but unverified-email login completion resets its consumed proof.

Production-built web served by owned nginx, against the owned production-mode API: 4/4 browser cases passed, zero retries, 16.8 seconds. This covers absent/forged REST+GraphQL proofs, real PoW with failed-password retry and successful login at 390/1440px, and zero login dispatch while verification is pending, failed or expired (including direct form submission). The expiry browser case exercises the widget event contract; service expiry uses a controlled clock in server tests.

Final server suite 140/140 passed; focused component/form tests 6/6 passed; types, lint and all four builds passed. Full web rerun is still completing. Prior failures and corrections are retained in the repository lesson. This is independent agent review, not GitHub non-author approval. CI remains open, including the known inherited Undici security failure pending #194; no deployment or email-delivery claim.

…61027

# Conflicts:
#	.agents/issues/INDEX.md
#	.agents/issues/security-audit-index.md
@github-actions

Copy link
Copy Markdown

🧪 Comprehensive Test Suite

  • Unit suites (Node 22.18.0 & 24.x) — core, web, server, mcp-server: ✅ passed
  • Installer & deploy config: ✅ passed

Full-stack smoke gate runs in the CI workflow.

@mvalancy

Copy link
Copy Markdown
Member Author

Composed final head 8c9712b7bda0c7515568c08bae710be4bea675a1 merges reviewed dev 32149ee61ea5436831d95d76e4c4b6dc2db619a3. Independent review confirmed all authentication code/tests are byte-identical to reviewed 283a375; the merge adds only the reviewed Undici dependency/test/lessons and preserves both index rows.

Fresh composed install, types, lint, all four builds and 163/163 harness tests passed. After restarting the owned production-mode API on the composed install, its built-nginx browser run passed 4/4, zero retries, 16.1 seconds. The authentication snapshot's 140 server and 332 web tests remain separately recorded, and exact-head remote CI has passed unit/build/security/real-Neo4j/installer checks while its full browser gate is still running. No deployment was performed.

The token-purpose/session-revocation follow-up for #184 is being developed on this branch's reviewed head to preserve the new CAPTCHA policy. It will be a separate dependent PR; it must not be integrated ahead of this PR's remaining gates.

@github-actions

Copy link
Copy Markdown

🧪 Comprehensive Test Suite

  • Unit suites (Node 22.18.0 & 24.x) — core, web, server, mcp-server: ✅ passed
  • Installer & deploy config: ✅ passed

Full-stack smoke gate runs in the CI workflow.

…61027

# Conflicts:
#	.agents/issues/INDEX.md
@mvalancy

Copy link
Copy Markdown
Member Author

The failed composition run 40573347298 exposed a development startup mismatch: CI ran npm run dev with NODE_ENV unset, so /config correctly required proof while the server still advertised quick-login accounts. The six basic smoke cases failed; this is retained as failure evidence, not counted as a pass.

Commit 00f9d9325282bf5ac8dcc909d45f9145129d85df adds an explicit development entry point that loads .env first and defaults only an absent mode. Explicit production, staging, or blank modes remain proof-required, production secret checks remain enforced, and quick-login discovery is restricted to development/test. Independent review found no remaining issue. Local validation: 146 server tests, 163 harness tests, clean install, all builds/types/lint, and 6/6 actual npm run dev browser smoke cases with no retries. The earlier four production CAPTCHA browser cases passed on the preceding auth implementation; this entry-point correction leaves production startup unchanged.

After LOD PR #192 merged, this PR was composed with live dev 8712389e24f567f5b3e6ed132c1ac5d4dafb21fa. Current frozen head is 7b1ebad827f6fb6a3006921dba1b03d974358766; the symptom-index conflict retained both branches’ entries. Composition review, fresh local gates, and exact-head CI are underway. No deployment or hosted parity is claimed.

@github-actions

Copy link
Copy Markdown

🧪 Comprehensive Test Suite

  • Unit suites (Node 22.18.0 & 24.x) — core, web, server, mcp-server: ✅ passed
  • Installer & deploy config: ✅ passed

Full-stack smoke gate runs in the CI workflow.

@mvalancy

Copy link
Copy Markdown
Member Author

Exact composition 7b1ebad827f6fb6a3006921dba1b03d974358766 passed clean pinned install, all builds/types/lint, 166/166 harness tests, and 4/4 production built-app browser cases (15.9s, zero retries) after restarting the owned API on this build. Independent composition review found no issues. The initial local harness command used the nonexistent test:harness script; that command failure is retained, and the actual repository command npm run test:unified:lib supplied the passing result.

Exact-head comprehensive 40579557449 is green; CI 40579557476 is still running. The prior 00f9 CI run was cancelled by this new push while its smoke gate was pending; it is not counted as a green run. No deployment or branch-protection change.

…ptcha-20261027

# Conflicts:
#	.agents/issues/INDEX.md
#	.agents/issues/security-audit-index.md
@mvalancy
mvalancy changed the base branch from dev to test/css-security-backport-20261027 October 27, 2026 21:24
@github-actions

Copy link
Copy Markdown

🧪 Comprehensive Test Suite

  • Unit suites (Node 22.18.0 & 24.x) — core, web, server, mcp-server: ✅ passed
  • Installer & deploy config: ✅ passed

Full-stack smoke gate runs in the CI workflow.

1 similar comment
@github-actions

Copy link
Copy Markdown

🧪 Comprehensive Test Suite

  • Unit suites (Node 22.18.0 & 24.x) — core, web, server, mcp-server: ✅ passed
  • Installer & deploy config: ✅ passed

Full-stack smoke gate runs in the CI workflow.

@mvalancy

Copy link
Copy Markdown
Member Author

Frozen composition 03b9ba8431f86cae0ed3c99bc586280c70afe65f includes reviewed editor focus #201 and dependency work. Independent review verified all CAPTCHA runtime/tests unchanged from 7b1ebad, all inherited content matches CSS f08077f, and both index conflicts retain all rows. Temporarily stacked on #199 so the displayed delta stays authentication-only.

Fresh clean install/build/types/lint, 146 server cases and 176 harness cases passed. Restarted the owned production-mode API on this built source and served its built SPA through the owned nginx fixture: 4/4 CAPTCHA browser cases passed in 13.5s, zero retries, including real proof, absent/forged REST+GraphQL proof and accessible desktop/phone retry behavior. Current CI 40586466883 remains pending; Node 22/24 + installer checks 40586466780 passed. The earlier editor-race CI failure remains retained; integration is not yet claimed.

@github-actions

Copy link
Copy Markdown

🧪 Comprehensive Test Suite

  • Unit suites (Node 22.18.0 & 24.x) — core, web, server, mcp-server: ✅ passed
  • Installer & deploy config: ✅ passed

Full-stack smoke gate runs in the CI workflow.

@github-actions

Copy link
Copy Markdown

🧪 Comprehensive Test Suite

  • Unit suites (Node 22.18.0 & 24.x) — core, web, server, mcp-server: ✅ passed
  • Installer & deploy config: ✅ passed

Full-stack smoke gate runs in the CI workflow.

@github-actions

Copy link
Copy Markdown

🧪 Comprehensive Test Suite

  • Unit suites (Node 22.18.0 & 24.x) — core, web, server, mcp-server: ✅ passed
  • Installer & deploy config: ✅ passed

Full-stack smoke gate runs in the CI workflow.

@mvalancy

Copy link
Copy Markdown
Member Author

Current CAPTCHA head a0fcaf882109a6b76d5f8f4278e4af2895629271 fixes a verification event-listener race exposed in token CI 40591509438. A visible widget could emit before its passive listener effect attached. Only the listener/reset block moves to layout timing; fetch/focus and authentication policy remain unchanged.

A deterministic React.Profiler regression emits at the first widget commit: old source fails 1/5, corrected source passes 5/5. Replacement, error, prior-action and unmount controls reject stale events. Independent review cleared exact source and downstream compositions. Local build/types/lint, 179 harness checks, and 353 web tests passed; the web run used bounded workers after retaining an unrelated unbounded 5-second test timeout and subsequent failure. No timeout/retry settings were relaxed. Rebuilt production SPA passed all four real CAPTCHA browser cases in 17.8s, one worker, zero retries.

Token current head 2b05ea00240d06d4e16ccbcce4d55ecd65476f8d and OAuth d83fd9ae627f4bebd1cbc30bab4ac6e3ad840c1b import exactly these four reviewed paths; their auth feature code is unchanged. Final current-head CI remains required. Earlier failed/cancelled runs remain evidence, not passes.

@github-actions

Copy link
Copy Markdown

🧪 Comprehensive Test Suite

  • Unit suites (Node 22.18.0 & 24.x) — core, web, server, mcp-server: ✅ passed
  • Installer & deploy config: ✅ passed

Full-stack smoke gate runs in the CI workflow.

1 similar comment
@github-actions

Copy link
Copy Markdown

🧪 Comprehensive Test Suite

  • Unit suites (Node 22.18.0 & 24.x) — core, web, server, mcp-server: ✅ passed
  • Installer & deploy config: ✅ passed

Full-stack smoke gate runs in the CI workflow.

@mvalancy

Copy link
Copy Markdown
Member Author

Imported reviewed LOD correction #207 without changing this feature's own implementation. The composition adds exactly four reviewed paths (renderer effect, regression, lesson and index); independent review verified complete tree/blob unions, parents and unchanged feature code. Source #207 passes LOD desktop/phone2/2, web346/346, harness175/175, smoke6/6, build/types/lint. Refreshed exact-head CI is active; earlier failures/cancelled superseded runs are retained and are not passes. The CSS acceptance failure is addressed by the isolated transition-ownership fix, not by retries or relaxed assertions.

@github-actions

Copy link
Copy Markdown

🧪 Comprehensive Test Suite

  • Unit suites (Node 22.18.0 & 24.x) — core, web, server, mcp-server: ✅ passed
  • Installer & deploy config: ✅ passed

Full-stack smoke gate runs in the CI workflow.

@mvalancy

Copy link
Copy Markdown
Member Author

Final correction composition is now 708f9203cb927cacb738b2349310e86279079d1f. Independent review verified the complete six-path import from reviewed LOD/camera-readiness head 7cbf292: source renderer, both browser regressions and lessons match byte-for-byte; feature-specific code and dependencies remain unchanged. The symptom index retains every previous row and adds the motion lesson. No instruction or authority changes.

The combined local motion suite passes 3/3 in 2.1 minutes with zero retries; combined LOD validation and fresh exact-head CI remain pending. Previous green heads do not establish this composition's final acceptance. Earlier LOD/rotation failures and insufficient title-geometry evidence remain retained. Integration follows #207 → #210 → #199 → #195 → #197 → #202 → #206 → #211, with native dev merge verification and post-merge CI before issue closeout. Independent agent review is not a GitHub non-author approval.

@mvalancy
mvalancy changed the base branch from test/css-security-backport-20261027 to dev October 28, 2026 00:08
@mvalancy
mvalancy marked this pull request as ready for review October 28, 2026 00:08
@mvalancy

Copy link
Copy Markdown
Member Author

Final native dev-only integration evidence for 708f9203cb927cacb738b2349310e86279079d1f: server-issued, action-bound CAPTCHA with expiry, bounded replay and preserved client commit timing. Independent exact-head implementation/composition reviews found no remaining findings. The reviewed camera corrections are included; feature-specific code is unchanged from its reviewed source.

CI40602589187 and Comprehensive40602589295 passed every applicable job. Downloaded strict artifacts verify smoke6, new-user42, LOD2, routes7, mobile27 and performance3, all with zero failed/warned/skipped cases, evidence errors, timeouts or nonzero executions. Effects, showcase, supported-Node coverage, installer and real-Neo4j gates also passed. The main/nightly-only production job is inapplicable to this dev PR.

The live base and complete merge result will be checked against the preceding reviewed stack tree immediately around the native operation. Expected resulting tree: 32a66d97890940cf2ec7f28406e5a47e0cc142e3. Retargeting a stacked PR to an equivalent dev tree changes no feature content. Earlier failures remain retained; no retry is substituted for a fix.

This uses the owner's standing dev administrator authority and does not claim a GitHub non-author approval. Issue closeout waits for successful validation of the integrated dev head; intermediate post-merge runs may be superseded by later reviewed stack integration and are not counted as passes. Main, release, deployment and protection remain unchanged.

@mvalancy
mvalancy merged commit e302e2d into dev Oct 28, 2026
16 checks passed
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