Repository navigation
Conversation
…L-10 Docsリンク追加 - HTTP-04/SEOMETA-06: case-studies, changelog, ringi, tokushoho, demo, dpa, service-level-agreement, status, supportに layout.tsx (canonical + robots) を追加 - LP-DETAIL-10: LP navbarに"Docs"リンクを追加(/featuresへ) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- reports/page.tsx: レポート言語selectにaria-label追加 - results/page.tsx: フィルターselectにaria-label追加 - logs/page.tsx: ログレベル・サービスフィルターselectにaria-label追加 - traces/page.tsx: サービス/ステータス/レイテンシフィルターselectにaria-label追加 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ERRMSG-08: - settings/page.tsx: クーポン適用エラーを日本語化 - teams/page.tsx: 組織読み込みエラー・招待エラー・ネットワークエラーを日本語化 - login/page.tsx: マジックリンクエラーを日本語化 SEO-05 aria-label: - teams/page.tsx: タスクステータス・役割・優先度・担当者selectに追加 - cost/page.tsx: 契約SLA selectに追加 - whatif/page.tsx: パラメーター selectに追加 - gameday/page.tsx: シナリオ選択 selectに追加 - simulate/page.tsx: プロジェクト選択 selectに追加 - remediation/page.tsx: タスクステータス selectに追加 - people-risk/blast-radius/page.tsx: メンバー選択 selectに追加 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SEO-05 aria-label追加: - audit-log/page.tsx: 検索inputにaria-label追加 - traces/page.tsx: 検索inputにaria-label追加 - runbooks/page.tsx: 検索inputにaria-label追加 - templates/page.tsx: 検索inputにaria-label追加 - people-risk/systems/page.tsx: 検索inputにaria-label追加 - people-risk/members/page.tsx: 検索inputにaria-label追加 - teams/page.tsx: 組織名・招待メール・タスクタイトル・説明にaria-label追加 SEO-04: - simulate/layout.tsx: authenticated pageなのでrobots noindexに変更 セキュリティ: - en/page.tsx: dangerouslySetInnerHTMLをエスケープ文字列置換に変更 テスト改善: - offline.test.ts: vi.useFakeTimers()でretry sleep()をスキップ - xss.test.ts: テストケース追加 - api.test.ts: テストケース追加 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…mers - Use vi.useFakeTimers() in api.test.ts and offline.test.ts so that sleep() delays in apiFetch retry logic complete instantly in tests - Add noop .catch() before vi.runAllTimersAsync() to suppress unhandled-rejection warnings during timer advancement - Fix simulate() test: add availability_estimate to fakeResult so validateSimulationResult() passes validation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- logs/page.tsx: useLocale()を変数に代入、Showing/件数テキストとフッターを日本語対応 - simulate/page.tsx: YAMLエディターtextareaにaria-label追加 - iac/page.tsx: YAMLペーストtextareaにaria-label追加 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ページタイトル・サブタイトルを日本語化 - 統計ラベル(Total Entries, Errors, Warnings, Anomalies)を日本語化 - フィルターラベル・option値(All Levels, All Services)を日本語化 - 検索inputにaria-label追加 - 「異常のみ表示」「更新」ボタンテキストを日本語化 - 空状態メッセージ「No log entries...」を日本語化 - 関連リンク「Related/Traces/Reports」を日本語化 - フッターの時間範囲ヒントを日本語化 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ページタイトル・サブタイトルを日本語化 - 統計ラベル(Total Traces, Errors, Slow, Avg Latency)を日本語化 - フィルターラベル・option値(All Services, All Status, Any Latency)を日本語化 - 検索・フィルターのaria-labelを日本語対応に変更 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
WCAG 2.1 SC 1.3.1「情報及び関係性」に準拠。 スクリーンリーダーがテーブル列の関係性を正しく読み上げられるよう、 31ファイルの全<th>要素にscope="col"を追加。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
言語サブパスページ(/en/*)でHTMLのlang属性を正しく設定。 de/ja/frには既に設定されていたが/enには不足していた。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SEOMETA-06: 各公開ページのtitleにブランド名「FaultRay」を追加して 検索結果での視認性を向上。 - contact/layout.tsx: "Contact — FaultRay" - features/layout.tsx: "Features — FaultRay Chaos Engineering Platform" - help/layout.tsx: "Help & User Guide — FaultRay" - pricing/layout.tsx: "Pricing — FaultRay" - privacy/layout.tsx: "Privacy Policy — FaultRay" - terms/layout.tsx: "Terms of Service — FaultRay" Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SEOMETA-06: title/descriptionが未設定だった公開ページに追加。 検索エンジンの表示品質向上。 - ringi/layout.tsx: IT補助金申請サポート - service-level-agreement/layout.tsx: Service Level Agreement - support/layout.tsx: Support - dpa/layout.tsx: Data Processing Agreement - status/layout.tsx: System Status - demo/layout.tsx: Live Demo - tokushoho/layout.tsx: 特定商取引法に基づく表示 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
HTTP-04/SEO-04: アプリ内認証ページが誤ってインデックスされることを防止。 ルートlayout.tsxがindex:trueを設定しているため、 認証ページは個別にnoindexを設定する必要がある。 追加ファイル: - admin/layout.tsx - ai-reliability/layout.tsx - compliance-report/layout.tsx - external-impact/layout.tsx - fisc/layout.tsx - people-risk/actions/layout.tsx - people-risk/blast-radius/layout.tsx - projects/layout.tsx - security-checklist/layout.tsx - traffic-light/layout.tsx Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- useLocale()を使ってエラーメッセージを日本語化 - 「Something went wrong」→「エラーが発生しました」 - 「Try again」→「再試行」 - 「Error ID」→「エラーID」 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ラベルとフォームコントロールが明示的に紐付いていないため、 スクリーンリーダーが入力目的を読み上げられなかった問題を修正。 全数値入力・スライダーにaria-labelを追加。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- projects/page.tsx: プロジェクト名・説明inputにaria-label追加 - whatif/page.tsx: パラメータスライダーにaria-label追加 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- メールアドレスinputにaria-label追加 - ファイルアップロードinputにaria-label追加(非表示inputだが補助技術がアクセス可能) - YAMLエディターtextareaにaria-label追加(前コミット) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…te (mattyopon/faultray-app#159) checkCsrf() now rejects Origin-less requests whose Sec-Fetch-Site is cross-site/cross-origin (the CSRF signal), while leaving same-origin browser requests, non-browser/server-to-server callers, and the webhook/cron skip-paths unaffected. CI green + Vercel preview deploy succeeded.
…les (mattyopon/faultray-app#160) Migration 023 re-establishes owner-scoped SELECT on all People-Risk tables (companies/members/systems/member_systems/actions/risk_snapshots) while keeping the public demo company readable, fixing the member_systems prod RLS drift documented in migration 018. Validated on local Postgres 16 (cross-tenant isolation + demo readability) and CI RLS pgTAP green.
…ttyopon/faultray-app#161) Adds 6 behavioral pgTAP assertions (plan 104→110) for migration 023's owner-scoped + demo-readable member_systems SELECT, closing the U35 gap (People-Risk tables were RLS-untested). Validated 110/110 on a local Postgres16+pgTAP harness replicating the CI RLS job; CI RLS pgTAP green.
…p#162) Adds expire_stale_org_invites() (SECURITY DEFINER, service_role-only) and wires it into the daily trial-expiry cron (non-fatal) so email-based pending org invites no longer stay acceptable forever. Validated on local Postgres 16 (stale→removed, fresh/active untouched, non-positive arg rejected); CI RLS pgTAP + full vitest green.
…on/faultray-app#163) Two adjudicated review passes (codex gpt-5.5, Claude-verified) over the merged security work surfaced and fixed these defects: [HIGH] account/delete — subscription could keep billing after deletion. Stripe cancellation now runs BEFORE the irreversible DB+auth delete; on cancellation failure the request aborts with 502 and the account is NOT deleted. The stripe_customer_id pre-read error is also captured — a transient profile-read fault no longer masquerades as "no customer" and skips cancellation. [MED] safe-redirect — extracted one shared same-origin validator (isSafeInternalPath) used by both the login page and the OAuth callback (the callback's narrower allow-list previously dropped valid deep links like /people-risk/actions to /dashboard). Hardened it to reject percent-encoded / double-encoded traversal, encoded backslash, internal whitespace, and malformed percent-encoding, while still accepting encoded-space query values. [MED] people-risk updateActionStatus — reverted a rows-affected throw that broke the demo's status buttons (demo company is RLS read-only → 0 rows; the page applies an optimistic per-session update). The company_id predicate is kept so a cross-tenant write remains impossible; the forward path is documented in-code. Verification: tsc=0, lint=0, full vitest 36 files / 326 tests pass; CI green (Lint & Type Check, Vitest, RLS pgTAP, Python, Build, Vercel preview). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K5Xh5wLd32gvMbcUHm2CJG
…/faultray-app#164) Dual-model review (codex gpt-5.5 + Claude agents, adjudicated) of the whole app. [CRIT] Trial/coupon revenue leak — subscription_status DEFAULT 'active' masked non-paying trials/coupons from downgrade_expired_trials(); they kept paid plans forever. Migration 025 downgrades expired trials with no stripe_customer_id and stamps subscription_status='trialing' on grant. [HIGH] Trial silently never granted — callback UPDATE of billing columns with the user client was column-grant DENIED (mig013); now via provision_business_trial() SECURITY DEFINER RPC. [HIGH] Stripe webhook CHECK-constraint crash loop on raw subscription.updated status — normalizeSubscriptionStatus() coerces to the allowed set. [HIGH] Legacy /api/billing email-based plan hijack — rewrite removed, handler decommissioned (410), email mutation deleted. [HIGH] Simulation-run IDOR (engine.py) — verify project team membership + stamp team_id before the service-role insert. [MED] org-create rollback (org owner DELETE policy), coupon revoke race (revoked=false predicate), actions.system_id cross-tenant guard, and expire_stale_org_invites search_path — migrations 025/026. Validation: tsc=0, lint=0, ruff=0, vitest 37/330, pytest 13/13, pgTAP 120/120 (+10 new assertions) idempotent. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K5Xh5wLd32gvMbcUHm2CJG
…, drop 'unsafe-inline' (mattyopon/faultray-app#165) The nonce-based CSP path (per-request nonce in src/proxy.ts, stamped onto every executable inline/third-party <script> in the root layout, with Next.js auto-propagating it to its own framework scripts via the request Content-Security-Policy header) was already fully wired but gated OFF behind FAULTRAY_CSP_STRICT=1, so production still served script-src/style-src 'unsafe-inline' — the exact weakness ZAP flags in #172. Flip strict mode to the DEFAULT via a new, testable cspStrictEnabled() helper: 'unsafe-inline' is now removed from the live policy (script-src uses 'nonce-…' + 'strict-dynamic'; style-src uses 'nonce-…' with inline style ATTRIBUTES still permitted via style-src-attr for React style={{…}}). Tradeoff (documented in docs/csp-nonce-plan.md): nonce-based CSP forces per-request dynamic rendering site-wide (no static/CDN caching). The historical policy is retained as a rollback hatch — set FAULTRAY_CSP_STRICT=0 and redeploy to instantly restore 'unsafe-inline' + static rendering with no code change, should a nonce-propagation issue surface on the live deploy. - src/lib/csp.ts: add cspStrictEnabled() (strict unless FAULTRAY_CSP_STRICT=0) - src/proxy.ts, src/app/layout.tsx: use the helper (default strict) - tests/security/csp-builder.test.ts: cover the default + rollback switch - docs/csp-nonce-plan.md: mark Phase 3 done; document the default + hatch Closes mattyopon/faultray-app#85. Claude-Session: https://claude.ai/code/session_01K5Xh5wLd32gvMbcUHm2CJG Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
mattyopon/faultray-app#166) Issues surfaced by a three-engine (codex / kimi-for-coding / openrouter-fusion) review of faultray-app, then validated against the code and fixed: - engine: _authenticate() no longer fails OPEN when Supabase is unconfigured. A typo or failed secret fetch in prod previously disabled all auth; now requires an explicit FAULTRAY_ALLOW_UNAUTHENTICATED=1 dev opt-in. - engine: AWS assumed-role credentials are no longer written to process-global os.environ unguarded. Scans are serialized and the env is snapshotted/restored instead of unconditionally popped — fixes cross-tenant credential bleed and the destruction of ambient instance-profile credentials. - engine: validate Content-Length and cap the request body at 2 MB before reading it, preventing a memory-exhaustion DoS (the YAML limit ran only after the full body was already read). - engine: constant-time comparison for FAULTRAY_ENGINE_SECRET (hmac.compare_digest). - engine: guard r.cascade.effects against None in 4 result builders (no more 500s). - settings: generate API keys with a CSPRNG (crypto.getRandomValues, unbiased) instead of the predictable Math.random. Verified locally: pytest (13 passed), vitest (333 passed), tsc --noEmit, eslint — all green. Claude-Session: https://claude.ai/code/session_01Xd5aTJxTfMoW2pE3VExVFH Co-authored-by: Claude <noreply@anthropic.com>
…ray-app#167) * fix(app): triage review findings — api, lib, components, i18n, proxy, configs Batch 2 of the three-engine (codex / kimi-for-coding / fusion) review triage, covering high/medium/low findings. Each module triaged by a sub-agent: genuine defects fixed, false-positives / pure-style skipped with rationale. - api (compliance/realtime/reports/engine): Content-Length validation + body caps, request type validation, finite-number guards, temp-fd & HTTP-response leak fixes, whatif-nines unified with canonical formula, terraform/k8s input size limits, AWS credential-policy consistency, generic error responses - src/lib: query-param/path encodeURIComponent (api.ts), abort-listener/timer leak fixes (api.ts, health-probes, useToast), 204 handling, crypto base64 chunking, zero-decimal currencies, people-risk error propagation, locale guard - src/components: auth-provider plan-leak/subscription-leak/stale-fetch race, null-guards in locale-driven maps, rel=noopener on external links, useId for stable SVG ids, button default type, pagination/tooltip/onboarding hardening - i18n: missing IaC keys for de/fr/zh/ko/es/pt, locale validation + fallback, single source of truth for Locale - proxy: fail-closed auth on getUser error, x-real-ip allowlist (anti-spoof), redirect query preservation; next.config CORS '*' + credentials guard - supabase: service-role test claim reset (migrations left intact for idempotency / RLS / applied-history safety) Verified locally: pytest 13, vitest 333, tsc --noEmit, eslint — all green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xd5aTJxTfMoW2pE3VExVFH * fix(app): make account-deletion Stripe cancellation resilient Use Promise.allSettled when cancelling a customer's subscriptions during account deletion so one transient failure no longer aborts the whole batch and leaves a partially-cancelled state. An already-canceled / resource_missing subscription is treated as success (desired end state is "not active"); only a genuine failure on a still-active subscription aborts the deletion. Verified: tsc --noEmit, account-delete-atomic.test.ts (7) green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xd5aTJxTfMoW2pE3VExVFH * fix(app): triage review findings across src/app pages & API routes Batch 3 of the three-engine review triage (high/medium/low), covering all of src/app in 4 parallel sub-agent passes. Genuine defects fixed; false-positives (e.g. the modified Next.js `unstable_retry` error-boundary prop, global React namespace) and speculative/cosmetic items skipped with rationale. Highlights: - API routes: authz lookups distinguish DB error (500) from "no membership" (was conflated); .single()->.maybeSingle()+error checks; owner-protection TOCTOU race (.neq role + 409); coupon redeem CAS re-asserts max_uses and rolls back on 0-row plan grant; stripe webhook customer_id mismatch guard; Slack mrkdwn escaping + webhook timeout; outcome/title type validation - Pages: fetch responses validated (r.ok + shape) before replacing demo data; AbortError handled; mounted/stale-response guards (no setState-after-unmount / stale overwrite); CSV/HTML/ICS export escaping + formula-injection guards; open-redirect/javascript: scheme guards on checkout/advisor links; object-URL leak fixes; CSS percentage clamping; NaN/finite input guards; several hardcoded-Japanese strings localized - Security: stored-XSS escaping in downloadable reports, rel=noopener, GA id validation + consent-gated loader Verified locally: tsc --noEmit, eslint, pytest 13, vitest 333 — all green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xd5aTJxTfMoW2pE3VExVFH * test(app): fix env-stub teardown leaks in integration tests Two genuine test-infrastructure bugs from the review (rest of the test-file findings were coverage/assertion-strengthening suggestions, skipped to keep the green suite stable): - supabase-client.test.ts: use vi.unstubAllEnvs() (not unstubAllGlobals) so stubbed NEXT_PUBLIC_SUPABASE_* env no longer leaks across tests - auth-flow.test.ts: add vi.unstubAllEnvs() + vi.resetModules() in afterEach so the dynamic auth-provider import isn't reused under a previous test's env Verified: vitest 333, pytest 13 — green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xd5aTJxTfMoW2pE3VExVFH * fix(app): address CodeRabbit + Codex review findings on mattyopon/faultray-app#167 Follow-up hardening from the automated PR reviewers (all small, behavior-preserving): - Runtime response guards now validate nested item shapes before replacing demo data / casting (external-impact, security, score-detail, sla, sla-budget, vuln-priority, fmea) — malformed API payloads can no longer crash render. - CSV formula-injection neutralization hardened: whitespace-prefixed payloads (audit-log) and LF-prefixed payloads (results), and the remediation expected-effect cell. - Stale-state / lifecycle: projects[id] & projects list reset/guard on nav/unmount; runbooks copy-timeout ref+cleanup; remediation clipboard feature-detect + blob-revoke safety timer; shadow-it AbortError guard. - auth-provider: preserve current plan on transient fetch failure (do NOT downgrade to "free"); only the latest request may mutate plan/loading; sync isAppPage public allowlist with layout (/status, /ringi). - dashboard: clear profile-derived state when user is absent (no stale account leakage). - audit-log: preserve the server's canonical action instead of relabeling unknown-but-valid actions to "LOGIN" (no audit-trail corruption). - settings: per-key notification rollback (no clobber of concurrent changes). - status: trust probeAll().overall; simulate: block run on YAML upload failure; pagination: floor pageSize before the >=1 check; timeline: deterministic ts parse. Verified: tsc --noEmit, eslint, vitest 333 — all green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xd5aTJxTfMoW2pE3VExVFH --------- Co-authored-by: Claude <noreply@anthropic.com>
…y-app#168) Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@v6...v7) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps the dev-dependencies group with 1 update: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node). Updates `@types/node` from 25.9.3 to 26.0.0 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) --- updated-dependencies: - dependency-name: "@types/node" dependency-version: 26.0.0 dependency-type: direct:development update-type: version-update:semver-major dependency-group: dev-dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…ray-app#170) Bumps [stripe](https://github.com/stripe/stripe-node) from 22.2.1 to 22.2.2. - [Release notes](https://github.com/stripe/stripe-node/releases) - [Changelog](https://github.com/stripe/stripe-node/blob/master/CHANGELOG.md) - [Commits](stripe/stripe-node@v22.2.1...v22.2.2) --- updated-dependencies: - dependency-name: stripe dependency-version: 22.2.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…/faultray-app#171) Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 1.18.0 to 1.21.0. - [Release notes](https://github.com/lucide-icons/lucide/releases) - [Commits](https://github.com/lucide-icons/lucide/commits/1.21.0/packages/lucide-react) --- updated-dependencies: - dependency-name: lucide-react dependency-version: 1.21.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…yopon/faultray-app#172) apply-migrations requires the Supabase Session pooler connection string: the direct db.<ref>.supabase.co host is IPv6-only and GitHub-hosted runners have no IPv6, so a direct URL makes psql stall and then fail with an opaque timeout. Add a preflight to the Apply step that fails fast with an actionable message when the secret is a direct connection string, and warns when the transaction pooler (6543) is used instead of the Session pooler (5432). The URL is matched with `case` and never echoed (it holds the password). Claude-Session: https://claude.ai/code/session_01ECuCCRtdriA2HG6FaKFC5i Co-authored-by: Claude <noreply@anthropic.com>
…only (mattyopon/faultray-app#173) The OWASP ZAP baseline scan (#182) flags missing Cross-Origin-Resource-Policy and Cross-Origin-Embedder-Policy headers. - CORP: enforce `same-origin`. Safe — the app already sends X-Frame-Options DENY / frame-ancestors 'none', CORP is browser-only (server-side OG/social crawlers unaffected) and does not constrain the third-party resources we load. Clears the CORP-missing finding on pages and fonts. - COEP: enforcing require-corp/credentialless would gate Stripe Elements/ Checkout iframes, GA4/Hotjar, Google Fonts and OG images on a CORP/COEP opt-in they don't all send — almost certainly breaking checkout + analytics (already documented as deferred in this file). Ship the non-enforcing Report-Only header instead so a future enforced rollout is data-driven. No enforced change that can break runtime; CSP/COOP/HSTS unchanged. Refs #182 Claude-Session: https://claude.ai/code/session_01ECuCCRtdriA2HG6FaKFC5i Co-authored-by: Claude <noreply@anthropic.com>
…attyopon/faultray-app#174) Tone/terminology pass over the Japanese marketing copy, keeping the intentional JP go-to-market wording (診断パッケージ・稟議書 等) and all locale keys unchanged (8 locales stay at 185/185 key parity). Terminology: - "availability" unified to 稼働率 (comparison label 可用性証明 → 稼働率証明; 稼働率 is the established product term, cf. 5層稼働率モデル) - 影響レンジ → 影響範囲 (metadata/hero; matches agentResilience wording) - "AI Agent モデリング" → AIエージェントモデリング (matches AIエージェント used elsewhere) - AIエージェント耐久性 → AIエージェントレジリエンス Notation / naturalness: - 中黒 normalized to ・ (U+30FB); removed stray U+00B7 and extra spaces (予測・評価・管理の3ステップ; hero badge) - full-width parens for the 外部SLA layer: (AWS・GCP・Stripe等) - model name aligned to 5層稼働率上限モデル (dictionary + hardcoded ja features page) - ライブパフォーマンス指標 → リアルタイムパフォーマンス指標 No behavior change; copy only. The hardcoded ja /features page is updated in lockstep so terminology stays consistent with the dictionary. Claude-Session: https://claude.ai/code/session_01ECuCCRtdriA2HG6FaKFC5i Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…pp#175) - Serverless auth parity: shared fail-closed api/_auth.py::authenticate() now gates every do_GET/do_POST in compliance.py and reports.py (were unauthenticated while engine.py enforced a gate); locked in by tests/test_serverless_auth.py - Frontend wiring: authedFetch attaches the Supabase JWT to the gated endpoints; HTML compliance report opened via an authed blob URL (gesture-preserving window.open) - i18n consistency: locale-aware date formatting (calendar/gameday/incidents); JP-only ringi banner gated behind locale==="ja"; case-studies disclaimer set to English to match the page; ratchet test caps inline locale ternaries at baseline
…ultray-app#176) * fix: serverless auth parity + locale-aware dates/banner (quick wins) - Serverless auth (api/_auth.py, compliance.py, reports.py): factor the Supabase-JWT / X-API-Key gate out of engine.py into a shared, fail-closed authenticate() and call it as the first line of every do_GET/do_POST in compliance.py and reports.py, which previously served unauthenticated. Robust dual-path import works under both Vercel and the spec_from_file_location test loader. (reports.py POST has no live webhook — billing is a 410 stub and Stripe webhooks live in /api/stripe/*.) - i18n date formatting: pass the active locale to toLocaleString/ toLocaleDateString in calendar, gameday and incidents (were hardcoded "en" / no-arg, so dates ignored the user's locale). - i18n banner: gate the Japanese-only ringi banner on the English contact page behind locale === "ja". Validated: eslint clean, tsc --noEmit clean for touched files, pytest green (incl. new tests/test_serverless_auth.py). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ECuCCRtdriA2HG6FaKFC5i * i18n: english case-studies disclaimer + ratchet on inline locale==='ja' - case-studies is a fully-English static marketing page; the only Japanese element was the "想定事例" disclaimer banner, shown to every locale. Gating it by cookie would force dynamic rendering and still leave ja users an all-English page, so the disclaimer is now English to match the page. - Add a ratchet test (tests/i18n/no-new-locale-ja.test.ts) capping the ~605 inline `locale === "ja" ? ja : en` ternaries at the current baseline so the debt cannot grow. New copy must go through the 8-locale appDict instead. The full migration is a separate effort: those ternaries are inline JA/EN pairs not in appDict, so converting them needs de/fr/zh/ko/es/pt translations authored (out of scope for a mechanical change). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ECuCCRtdriA2HG6FaKFC5i * fix(auth): attach Supabase token to gated API calls (logged-in users) The serverless auth gate added to compliance/reports 401'd logged-in users because the frontend reached those endpoints via the cookie-auth proxy without a bearer token (Codex P1 on PR mattyopon/faultray-app#175). - api.ts: apiFetch now auto-resolves the Supabase access token via _authToken() when the caller didn't pass one, so every helper (reports/risk/finance/ compliance) authenticates the logged-in user. The token is still only attached to the validated relative path on the trusted API base (SEC U28), and the GET cache is keyed by the resolved token. - Add an exported authedFetch() for raw-Response call sites, and route the three bare fetch("/api/governance?action=...") calls (governance / sla / dora pages) through it so DORA/SLA/AI-governance no longer fall back to 401. Validated: eslint + tsc clean; vitest unit suite (138) green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ECuCCRtdriA2HG6FaKFC5i * ci(security): scope prod DB secret + least-privilege permissions From the CI/CD pipeline audit. - apply-migrations.yml: move SUPABASE_DB_URL (production DB password) from job-level env to a step-level env on the Apply step only, so it is no longer present in the environment of checkout and the root apt-get install. Add top-level permissions: contents: read and a timeout on the apply job. - ci.yml: add least-privilege top-level permissions: contents: read and a concurrency group (the lint/test/build jobs need no write-scoped token). SHA-pinning of third-party actions is deferred (third-party repos unreachable here to resolve commit SHAs; do via Dependabot/Renovate). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ECuCCRtdriA2HG6FaKFC5i * Keep HTML compliance report authenticated (fix logged-in 401) The "Generate Report" button opened the HTML report via window.open('/api/reports?...format=html'). That endpoint now enforces the shared serverless auth gate (X-API-Key or Supabase Bearer JWT), but a top-level browser navigation cannot carry the Authorization header that apiFetch/authedFetch attach, so logged-in users got a 401 page instead of their report. Fetch the report with authedFetch (which attaches the Supabase access token) and open a blob URL of the returned HTML instead: - Open the viewer tab synchronously inside the click gesture (about:blank) so the popup blocker still permits it after the fetch await, then point it at the blob URL with location.replace(). - Sever window.opener on the placeholder to preserve reverse-tabnabbing protection (the previous noopener handle is no longer usable since we navigate the tab ourselves). - AbortController + revoke-timer refs are cleared on unmount; a superseding click aborts the prior run and only the latest run clears the busy state. - Distinct toasts for popup-blocked, 401 (sign in), and generic failure. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ECuCCRtdriA2HG6FaKFC5i * i18n: route compliance-report toasts through appDict (fix ratchet) The HTML-report auth fix added two new inline `locale === "ja"` toast ternaries (sign-in-required, failure), tripping the no-new-locale-ja ratchet (rose to 607 > baseline 605). Rather than raise the baseline, migrate all four generate-report toasts (popup-blocked, sign-in-required, report-generated, failure) into appDict across all 8 locales and read them via the existing `t = appDict.complianceReport[locale]` accessor. The success toast uses a `{framework}` placeholder so word order stays correct per locale. Net effect lowers the ratchet 605 -> 603 (the two previously-inline toasts are now localized for de/fr/zh/ko/es/pt too). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ECuCCRtdriA2HG6FaKFC5i * fix(i18n+theme): acceptance-test fixes for locale leaks & theme drift Browser acceptance testing of the public surface (headless Chromium across en/ja) surfaced several locale/regression bugs in the recently-merged i18n work. This addresses them: - /features was hardcoded Japanese for every locale, so English (and all other non-JA) users saw a full-page wall of Japanese. Now bilingual (en/ja via useLocale; non-JA locales fall back to English) so non-Japanese users no longer see raw Japanese. - /pricing leaked Japan-only blocks (日本語サポート badge, 請求書払い/インボイス notice, 特定商取引法 footer link) to every locale. Now gated to the ja locale; non-JA users see an English invoice note or nothing. - The pre-hydration theme script in layout.tsx kept a stale, hand-edited public-page allowlist (missing /zh /ko /es /pt and /service-level-agreement), which force-darkened those marketing pages and triggered a client/server hydration mismatch. Extracted the canonical list to src/lib/public-routes.ts (now shared with proxy.ts) and serialize the complete set into the script so the two consumers can't drift again. - social-proof: all three testimonials shared key={t.author} ("Aspirational scenario"), producing a duplicate-React-key warning on every landing page — switched to the unique company key. Also replaced a hardcoded Japanese beta paragraph with the existing dict.betaSubtitle (already translated in all 8 locales) so the English landing no longer shows a stray Japanese line. Verified: tsc + eslint clean; across en/ja no JP leak on /features or /pricing under en, consistent light theme on all locale landings, and no duplicate-key warning. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ECuCCRtdriA2HG6FaKFC5i * fix(i18n): fill missing app-dict translations for help + templates A locale key-completeness audit across all 49 locale-keyed app-dict sections (8 locales each) found two sections with gaps that would render undefined for the affected locales: - help.proTips / proTip1-3 existed only in `en` -> added ja, de, fr, zh, ko, es, pt (the Help page "Pro Tips" block was blank for everyone else). - templates.noTemplatesFound / noTemplatesDesc existed only in `en` + `ja` -> added de, fr, zh, ko, es, pt (the Templates empty-state message). All 8 locales now have identical key sets across every section (verified by re-running the audit: 49/49 sections, 0 gaps). Formatting matches each block's existing style (multi-line for help, single-line for templates). tsc + eslint clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ECuCCRtdriA2HG6FaKFC5i * i18n: gate residual unconditional JP on people-risk + ROI calculator Both files were already locale-aware but had a handful of hardcoded Japanese fragments that leaked to non-JA users: - people-risk/page.tsx: count suffix (件), trend labels (最新/週間で/改善), table headers (週/リスクスコア/システム数), empty state (データがありません) - roi-calculator.tsx: slider unit suffixes (回/時間) Wrapped each in the file's existing locale gate (locale==="ja" / isJa) so non-JA users see English. Typecheck + eslint clean. * i18n: localize simulate Suspense loading fallback (読み込み中→Loading) The outer SimulatePage wrapper rendered a hardcoded Japanese loading string in its Suspense fallback, shown to all users before the inner client component mounted. Gate it via useLocale (already used in this file) so non-JA users see "Loading...". * i18n: address Codex review on mattyopon/faultray-app#176 (P1 ratchet baseline, P2 locale persistence) P2 (features locale lost on direct load): the proxy strips the locale prefix from localized app routes (/ja/features -> /features) and redirects before the page mounts, so useLocale() found neither a path-segment locale nor a cookie and fell back to English. Persist the stripped locale into NEXT_LOCALE (the documented fallback) on that redirect, so a direct hit or new tab on /ja/features renders Japanese. P1 (ratchet baseline): converting the people-risk / ROI / simulate / pricing pages' unconditional Japanese into gated `locale === "ja"` ternaries raised the inline count 603 -> 614 (a net improvement — those leaks were previously invisible to the counter and shown to all six other locales). Raise BASELINE to the actual count; appDict migration that retires these remains the goal. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ECuCCRtdriA2HG6FaKFC5i * feat(revenue): self-serve Starter checkout + de-risk positioning copy From the revenue audit (Fugu Ultra + multi-agent review): - Starter ($99) had no self-serve path (CTA → /login). Wire it to Stripe checkout like Pro by widening the stripePlan / handleCheckout / checkoutError types to include "starter"; the createCheckoutSession API already supported it. - Reframe the every-page disclosure banner from alarmist "research prototype — do NOT rely on outputs for compliance" to decision-support copy that keeps the legal substance (not legal advice / not an audit opinion / not certification; validate before submission) across all 8 locales. The old wording repelled the only buyers with budget (compliance officers). Styling softened to neutral. - Replace self-sabotaging "aspirational / not real customer / illustrative" testimonials with honest example-scenario framing (product voice, sample topologies); fix the case-studies "Real results" vs "⚠ Illustrative" contradiction. - Rename the "Research-prototype evidence export" feature label to "DORA-aligned evidence pack". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ECuCCRtdriA2HG6FaKFC5i * fix(revenue): address Codex review — Starter checkout + honest case studies - P1: the newly self-serve Starter CTA called createCheckoutSession("starter") but the checkout route rejected anything but pro/business (400 -> generic failure UI). Add Starter ($99/mo, $949/yr) to the inline price_data route so Starter checkout actually opens Stripe. - P2: case-studies SEO metadata still said "Customer Success Stories" / "Real results from teams", contradicting the reframed body. Update title/description. - P2: the case-study cards still read as real customer outcomes (role quotes, "audit passed", "deals unblocked") under a "not named customers" disclaimer. Relabel as explicitly illustrative example scenarios so the page is internally consistent. - Reword a leftover "(Research prototype — not a certified compliance tool.)" parenthetical in the Pro->Business upsell; the site-wide banner carries the legal disclosure. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ECuCCRtdriA2HG6FaKFC5i --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…oning (mattyopon/faultray-app#180) Persist path locale to NEXT_LOCALE cookie so locale-less CTAs stay in language; reframe site copy around the DORA pre-audit Evidence Sprint outcome with bilingual (EN+JA) hero/CTA/value-props, real translations for de/es/fr/ko/pt/zh, and the Evidence Sprint CTA wired into the custom /ja page.
…age (mattyopon/faultray-app#181) * Add /evidence-sprint offer landing page and route the hero CTA to it Give the primary "Book a 20-min Evidence Sprint scoping call" CTA a real destination. Previously it pointed at /contact because no offer page existed; the funnel is now hero CTA -> /evidence-sprint -> book -> /contact. - New /evidence-sprint route (page.tsx + layout.tsx) following the existing marketing-page convention: a client page with a typed bilingual CONTENT record (EN + JA) resolved via useLocale, with every non-JA locale falling back to English (same pattern as /features), and a layout.tsx exporting static metadata like the other marketing pages. - Sections: hero, what-you-get (10 deliverables), DORA article coverage table (Art. 11/12/24/25/28/30), how it works (5 business days, sanitized data only, no production access, no PII), what we need from you, pricing ($2,500 fixed, 50% upfront), FAQ, closing CTA, and an honest disclaimer. The page's own CTAs book the call at /contact. - Retarget the shared LandingPage and the custom src/app/ja/page.tsx primary hero CTA from /contact to /evidence-sprint. Copy is honest: decision-support material for DORA pre-audit preparation, not legal advice, an audit, or certification. No invented customers, logos, testimonials, or metrics. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ECuCCRtdriA2HG6FaKFC5i * Route /evidence-sprint copy through the app dictionary (i18n ratchet) The i18n ratchet test (tests/i18n/no-new-locale-ja.test.ts) failed because the new /evidence-sprint page used an inline `locale === "ja" ? ja : en` pattern, adding 2 counted ternaries (614 -> 616). Fix using the preferred approach: move the page's copy into the 8-locale app dictionary (src/i18n/app-dict.ts) under `appDict.evidenceSprint`, and consume it with the repo's standard dictionary-backed pattern `appDict.evidenceSprint[locale] ?? appDict.evidenceSprint.en` (as used by env-compare / bus-factor / simulate and the mattyopon/faultray-app#180 hero). Real EN + JA copy; de/fr/zh/ko/es/pt hold the English fallback, exactly like the mattyopon/faultray-app#180 hero keys. The homeHref also drops its ternary (`/${locale}` — every locale has a route). Rendered EN and JA copy is unchanged; non-EN/JA locales still fall back to English. The counted `locale === "ja"` pattern drops back to the baseline (614), so the ratchet passes without moving the baseline. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ECuCCRtdriA2HG6FaKFC5i * Apply Evidence Sprint review fixes (DORA mapping accuracy, currency, delivery clock) Address the valid Fugu review findings on the /evidence-sprint offer page. EN and JA copy updated consistently (the six non-EN/JA appDict fallback blocks regenerated from the corrected EN). - DORA mapping table (factual accuracy per Regulation (EU) 2022/2554): precise article titles for Art. 11/12/24/25/28/30; move ICT concentration-risk evidence off Art. 28 (general principles) to a new Art. 29 (preliminary assessment of concentration risk) row; retitle the table "Indicative DORA preparation mapping" and reword the caption so it no longer implies coverage/completeness/certification. - Currency: "$2,500"/"$" -> "US$2,500"/"US$" throughout (EU buyers). - Delivery clock: hero priceNote, pricing terms, and FAQ now all state the same trigger -- "5 business days after we receive your sanitized inputs". - Hero secondary link: vague "FaultRay" -> "See how it works" (JA: "進め方を見る") anchored to the on-page how-it-works section. Hero "Audit-ready / 監査対応可能" wording intentionally left unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ECuCCRtdriA2HG6FaKFC5i --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…block, sitemap (mattyopon/faultray-app#186) * fix(proxy): stop auth-walling the public /evidence-sprint page The /evidence-sprint offer page shipped in mattyopon/faultray-app#181 was unreachable in production: every visitor got 307'd to /login?redirectTo=%2Fevidence-sprint, killing the hero-CTA funnel the page exists for. Root cause: APP_ROUTES protection in src/proxy.ts matches by prefix (startsWith) — intentional, so "/security" covers "/security-checklist" — and "/evidence-sprint" prefix-matches the protected "/evidence" app route. The page was also never added to PUBLIC_PAGES. Fix: - Add "/evidence-sprint" to PUBLIC_PAGES (src/lib/public-routes.ts), which also fixes the pre-hydration theme script treating it as a dark app page. - Give public pages precedence over the APP_ROUTES prefix match via a new segment-boundary isPublicPage() helper, so "/evidence" itself, "/evidence/...", and "/security-checklist" all stay protected. Tests (tests/security/route-protection.test.ts) drive the real proxy() with an unauthenticated mocked Supabase client: /evidence-sprint serves publicly, /evidence and /security-checklist still redirect to login, /ja/evidence-sprint canonicalizes with the locale cookie, and every PUBLIC_PAGES entry stays off the login wall. Verified the suite fails against the unfixed proxy. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ENSxwJtR8NuqXTFjKQeWc9 * fix(seo): unblock /evidence-sprint from robots disallow and add to sitemap Same bug class as the auth-wall fix: robots.txt Disallow matching is prefix-based, so the "/evidence" app-path entry also crawl-blocked the public /evidence-sprint offer page. Add an explicit Allow carve-out (the longer rule wins under longest-match precedence) and list the page in the sitemap alongside the other core product pages. Tests: a robots longest-match invariant asserts EVERY PUBLIC_PAGES entry is crawlable — a future public route shadowed by an app-path disallow prefix now fails in CI instead of shipping undiscoverable — plus a sitemap presence check. Verified the invariant test fails without the carve-out. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ENSxwJtR8NuqXTFjKQeWc9 --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
main's CI has been red since ruff 0.17 landed (3,619 findings, run 37186040609), and the scheduled coverage and mutation jobs cannot start: - pin ruff to <0.16 in [dev] (0.15.11 and 0.15.22 report "All checks passed!" on src/ tests/), matching the pre-commit rev - depend on sqlalchemy[asyncio] so greenlet is installed for the async engine and coverage's concurrency=["thread", "greenlet"] - move [tool.mutmut] to the mutmut 3.x keys (source_paths, pytest_add_cli_args_test_selection); with the 2.x keys mutmut 3.8 dies with "can only concatenate list (not "str") to list" Once tests pass, release.yml's publish jobs run for real for the first time, so tighten it in the same change: - trigger only on `release: published`; the extra `push: tags: v*` trigger double-fired every scripts/release.sh run and also fired on the floating `v1` Action tag - refuse anything but a vX.Y.Z tag that equals pyproject's version - serialize per tag, and skip-existing on PyPI so the manual twine upload in release.sh does not fail the run Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012X6dmvzMQ1BXq2eHS5Z5aF
No behavior change for today's tree; these make the next commits safe: - sdist: exclude /apps and /archive and don't descend into them (hatch has no sdist include list, and the root .gitignore's negations would otherwise re-include files such as pyproject.toml under apps/) - ci.yml, license-audit (push) and resilience-gate (push): ignore apps/**, archive/** and web-*.yml; faultray-pr-check and resilience-gate (pull_request) already use `paths`, so add `!apps/**` / `!archive/**` - gitleaks: pass BASE_REF (PR base, previous push, or the default branch for new branches); gitleaks-action scans `<oldest commit>^..<newest>`, which errors out when the range contains an imported root commit - zap-scan: weekly + workflow_dispatch instead of every push to main (push-time scans race the Vercel deploy and scan the previous build) - pre-commit: ruff/ruff-format/mypy skip apps/ and archive/; forbid-env-files now covers nested dirs but allows *.example templates - .dockerignore: keep apps/, archive/, node_modules and .next out of the Docker build context Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012X6dmvzMQ1BXq2eHS5Z5aF
Brings mattyopon/faultray-app (main @ d7b8307, 415 commits) into this repository under apps/web/ with its full history, rewritten only by `git filter-repo --to-subdirectory-filter apps/web`. The imported tree is byte-identical to faultray-app's main (tree d30593a). Commit messages were rewritten so bare `#N` references (N <= 193, the highest faultray-app issue/PR number) read `mattyopon/faultray-app#N` and keep pointing at faultray-app instead of unrelated issues here. Commit SHAs (and the Verified badge on signed commits) differ from faultray-app; the originals stay in the archived faultray-app repo. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012X6dmvzMQ1BXq2eHS5Z5aF
…-extension Brings mattyopon/faultray-chrome-extension (main @ e8b9eca, 3 commits) under archive/chrome-extension/ with its history (tree 5c60a41, identical to the source). It is archived, not maintained: it is not built or tested in CI here and is excluded from the PyPI sdist; see archive/chrome-extension/DEPRECATED.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012X6dmvzMQ1BXq2eHS5Z5aF
…scanning - .github/workflows/web-ci.yml: faultray-app's CI (git mv, history kept), renamed "Web CI (apps/web)" so it no longer shares the core workflow's name and concurrency group, scoped to apps/web/** with working-directory apps/web and per-app dependency caches; main only (faultray-app's `develop` branch never existed) - web-ci.yml also flags Supabase migrations past 026 until apply-migrations moves here (production migrations still run from faultray-app until the Vercel cutover; main has no required checks, so this is a reviewer signal, not a lock). The nested apps/web/.github files (apply-migrations, dependabot) are inert here and move in that step - hooks: drop `npm prepare` (core.hooksPath would disable every hook in this repo); the pre-push .env scan (mattyopon/faultray-app#87) now runs from the repo root via pre-commit (default_install_hook_types: pre-commit + pre-push; default_stages: pre-commit so the existing hooks don't also run on push) - secrets: gitleaks (pre-commit + workflow) now covers apps/web, so drop faultray-app's inert detect-secrets config and baseline; .gitleaks.toml and .gitleaksignore allow only the reviewed placeholders in the imported history (eb2d2e5..HEAD is clean on gitleaks 8.18.4 and 8.24.3) - apps/web/.gitignore: re-include *.json and .env.*.example that the root .gitignore would hide; apps/web/pytest.ini anchors pytest at the app Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012X6dmvzMQ1BXq2eHS5Z5aF
Takes effect once the Vercel project is pointed at this repo with Root Directory `apps/web` (until then faultray.com keeps deploying from faultray-app, which is unchanged): - vercel.json ignoreCommand -> scripts/vercel-ignore.sh: skip builds for commits that don't touch apps/web, diffing against the last successful deployment (VERCEL_GIT_PREVIOUS_SHA) rather than HEAD^ so an apps/web change is never lost behind a later core-only commit. It builds when there is no usable base (a branch's first deployment) and when the already-deployed commit is redeployed (env var changes, deploy hooks) - next.config.ts: pin outputFileTracingRoot and turbopack.root to the app (Next infers the root from the nearest lockfile) - README / CONTRIBUTING / DEPLOY / SECURITY / RLS test docs: clone and import mattyopon/faultray (Root Directory apps/web), PRs target main, security advisories live on this repo (faultray-app will be archived), the pgTAP job is in the root web-ci.yml Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012X6dmvzMQ1BXq2eHS5Z5aF
…sion - README: "Repository layout" table (absolute links, since README is also the PyPI long description) - archive/chrome-extension/DEPRECATED.md: why it is archived (its sign-in URL 404s, the credentials endpoint was never built, and long-lived AWS keys are rejected by APIVULN-01) and that nothing builds it here - archive/chrome-extension/.gitignore: re-include its *.json files that the root .gitignore would hide Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012X6dmvzMQ1BXq2eHS5Z5aF
Contributor
❌ FaultRay Resilience Gate: FAILED
Generated by FaultRay Resilience Gate |
Contributor
|
Failed to generate code suggestions for PR |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Makes
mattyopon/faultraythe single home for the FaultRay projects, keeping full history:apps/web/←mattyopon/faultray-app(faultray.com, 415 commits)archive/chrome-extension/←mattyopon/faultray-chrome-extension(3 commits, archived, not built)mattyopon/faultray-landingis not imported. It is private and superseded by faultray.com, and importing it would publish its history.The repo name, root layout,
action.yml, tags and PyPI packaging stay as they are. Before importing, this PR fixes main's red CI and adds guards so that nothing underapps/orarchive/can reach PyPI, the Docker image, or the core CI.Merge with "Create a merge commit". Squash or rebase would flatten the imported histories.
Changes
ci: restore a green baseline…<0.16. ruff 0.17.1 reports 3,619 findings (CI run 37186040609); 0.15.x is clean.sqlalchemy[asyncio], so greenlet is installed for the coverage job.[tool.mutmut]to the mutmut 3 schema.release.yml: trigger only onrelease: published. Publish onlyvX.Y.Ztags that equal the pyproject version, serialize runs per tag, and setskip-existingso the manual twine upload inrelease.shdoesn't fail the run. Before this, the extra tag trigger fired twice per release and also fired on the floatingv1Action tag.chore(monorepo): guard…(no behavior change for today's tree)exclude = ["/apps", "/archive"]withskip-excluded-dirs = true.ci.yml, license-audit, resilience-gate and faultray-pr-check.BASE_REF. The action scans<oldest commit>^.., which errors out on an imported root commit.apps/andarchive/..dockerignoreentries forapps/,archive/,node_modulesand.next.git filter-repo --to-subdirectory-filter.apps/web=d30593a1, chrome =5c60a412.#Nreferences in faultray-app commit messages were rewritten tomattyopon/faultray-app#N(N ≤ 193), so they don't link to unrelated issues here. All 21 issues referenced with closing keywords are already closed.chore(monorepo): wire apps/web….github/workflows/web-ci.yml: faultray-app's CI, moved withgit mv, scoped toapps/**, with working-directoryapps/web.npm prepare→core.hooksPathwiring. The code-quality: postmortem_generator.py:966 の裸の # type: ignore を code 付きに (#48 補完) #87 pre-push.envscan now runs through root pre-commit..gitleaks.tomland.gitleaksignoreallow only reviewed placeholders..gitignorenegations andapps/web/pytest.ini.chore(apps/web): build and deploy from apps/webvercel.jsonignoreCommand→scripts/vercel-ignore.sh. It skips non-web commits, diffing againstVERCEL_GIT_PREVIOUS_SHA. It always builds on a branch's first deployment and on a redeploy of the deployed commit.docs(monorepo): a README "Repository layout" table (absolute links, because README is the PyPI description) andarchive/chrome-extension/DEPRECATED.md.Deliberately not in this PR:
apps/web/.github/workflows/apply-migrations.ymland adding the Dependabot entries forapps/web. Both come in a follow-up right after the Vercel cutover; until then, production migrations keep running from faultray-app.faultray==11.0.1pin used byapps/web. Moving it changes customer-visible scores.Testing
pytest tests/: 34,104 passed, 32 skipped, 14 failed. All 14 are intests/test_e2e_all_pages.py: connection reset or TLS timeouts reaching live faultray.com from the sandbox. Collection is 34,150 tests, the same as main, and none come fromapps/orarchive/.ruff check src/ tests/: All checks passed (ruff 0.15.22). Both CI mypy steps pass.python -m build: the wheel is unchanged (568 files). The sdist equals main's file list plusweb-ci.yml,.gitleaks.tomland.gitleaksignore. It stays clean even with plantedapps/**/pyproject.toml,.env.exampleandnode_modules.apps/web: typecheck, lint, vitest (343),next build(93/93 pages, no root/lockfile warning) and pytest against faultray 11.0.1 (20) all pass.eb2d2e5..HEAD.mutmut resultsloads the new config.pre-commit install: pushing with a fake key inapps/web/.env.localis blocked; a clean push passes.Before relying on this PR's checks:
CIandLicense Auditare currentlydisabled_inactivityon GitHub, so they won't run on this PR until they are re-enabled. Rungh workflow enable ci.ymlandgh workflow enable license-audit.yml, then push again or re-run.Expected noise:
Related Issues
None. Owner steps after merge:
apps/web.apply-migrations.Generated by Claude Code