Cleanup of SaaS code (#6669)

# Description of Changes
De-AI comments and fix ridiculously indented code
This commit is contained in:
James Brunton
2026-06-16 11:49:13 +01:00
committed by GitHub
parent 42c1cce56d
commit 9a883be697
20 changed files with 79 additions and 99 deletions
@@ -119,8 +119,11 @@ test.describe("1. Authentication and Login", () => {
// Full page reload forces the SPA to re-check auth with the backend
await page.reload({ waitUntil: "domcontentloaded" });
// Step 3: Verify the user is redirected to the login page
await expect(page).toHaveURL(/\/login/, { timeout: 15000 });
// Step 3: Verify the user is redirected to the login page. The redirect
// is driven client-side after the SPA re-bootstraps (session check +
// config fetch + backend probe), which can outrun a 15s budget on a
// loaded CI runner, so allow longer here.
await expect(page).toHaveURL(/\/login/, { timeout: 30000 });
// Step 5: Log in with valid credentials
await page.locator("#email").fill("admin");
@@ -21,9 +21,8 @@ describe("scoreMatch", () => {
});
it("rejects unrelated words that share half their letters", () => {
// Regression: the old fallback accepted 50% relative Levenshtein
// similarity, so longer queries matched more junk (rotate vs update is
// edit distance 3 of 6)
// Unrelated words can share many letters (rotate vs update is edit
// distance 3 of 6) but must not be treated as a fuzzy match.
expect(isFuzzyMatch("rotate", "update")).toBe(false);
expect(isFuzzyMatch("rotate", "create")).toBe(false);
expect(isFuzzyMatch("rotate", "private")).toBe(false);
@@ -20,8 +20,8 @@ function makeEntry(name: string, tags: string): ToolRegistryEntry {
};
}
// Real names and tags from the en-GB translations; these tools previously
// polluted results for partial queries like "rotat" and "rotate"
// Real names and tags from the en-GB translations, chosen because they share
// letters with "rotat"/"rotate" and stress the partial-query filtering.
const registry: Partial<ToolRegistry> = {
rotate: makeEntry(
"Rotate",
@@ -72,9 +72,8 @@ describe("filterToolRegistryByQuery", () => {
});
it("only returns Rotate for every prefix of 'rotate'", () => {
// Regression: "rotat" used to also pull in Redact, Annotate, Compare and
// Adjust Colours/Contrast, and "rotate" additionally Scanner Effect,
// Change Metadata, Add Password and Air-gapped Setup
// Prefixes of "rotate" must not leak tools that merely share letters
// (Redact, Annotate, Compare, Adjust Colours/Contrast, etc.).
expect(idsFor("rota")).toEqual(["rotate"]);
expect(idsFor("rotat")).toEqual(["rotate"]);
expect(idsFor("rotate")).toEqual(["rotate"]);
@@ -158,6 +158,6 @@ export const ListSection: Story = {
),
};
// Note: the setup + edit wizard now embeds the Watch Folders automation builder
// (its Workflow step), which needs the ToolWorkflow context so the wizard is
// The setup + edit wizard embeds the Watch Folders automation builder (its
// Workflow step), which needs the ToolWorkflow context - so the wizard is
// exercised in-app, not via an isolated story here.
@@ -39,8 +39,8 @@ interface PolicyToolConfigStepProps {
initialOperations: AutomationOperation[];
/**
* The preset's default operations. Their params seed any tool whose saved
* value is still at the tool's own default — so e.g. a policy saved before the
* PII patterns existed inherits them rather than running with an empty list.
* value is still at the tool's own default — so e.g. a policy saved with the
* PII list at its default inherits the preset patterns rather than running empty.
*/
presetOperations: AutomationOperation[];
/** Used to name the built pipeline definition. */
@@ -1,5 +1,5 @@
/**
* External store for real backend policy runs (Phase B: auto-run on upload).
* External store for real backend policy runs (auto-run on upload).
*
* The auto-run controller fires a backend run for each enabled policy × each
* newly-uploaded file and records it here; the detail view's activity feed reads
@@ -3,8 +3,6 @@
* config page shows (one section per tool). Tools can be configured + toggled
* on/off, but not added or removed. Each id is a frontend tool-registry key (and
* maps to that tool's backend endpoint via the registry's operationConfig).
*
* Only Security is wired today; other categories follow.
*/
export const POLICY_TOOL_CHAINS: Record<string, string[]> = {
// Security: redact PII + watermark + sanitize (strips JS). Which are enabled
@@ -1,5 +1,5 @@
/**
* Auto-run controller (Phase B): every enabled policy enforces on every uploaded
* Auto-run controller: every enabled policy enforces on every uploaded
* file. Watches the session's files and, for each (active policy × not-yet-run
* file), fires a real backend run (`POST /api/v1/policies/{id}/run`) and polls it
* to completion, recording progress in {@link policyRunStore} for the activity
@@ -5,8 +5,8 @@ describe("policy definitions integrity", () => {
it("every category has a matching config entry", () => {
for (const cat of POLICY_CATEGORIES) {
expect(POLICY_CONFIG[cat.id], `config for ${cat.id}`).toBeDefined();
// A category may have no policy-level setting fields (e.g. Security's were
// all unwired and removed); fields is required but can be empty.
// A category may have no policy-level setting fields; fields is required
// but can be empty.
expect(Array.isArray(POLICY_CONFIG[cat.id].fields)).toBe(true);
expect(POLICY_CONFIG[cat.id].rules.length).toBeGreaterThan(0);
// Every preset seeds a real, non-empty pipeline (the category→steps map).
@@ -24,7 +24,7 @@ import type {
const ICON_SX = { fontSize: "1rem" } as const;
/** The 5 policy categories, in the prototype's narrative order. */
/** The 5 policy categories, in display order. */
export const POLICY_CATEGORIES: PolicyCategory[] = [
{
id: "ingestion",
@@ -69,7 +69,7 @@ export const POLICY_CATEGORIES: PolicyCategory[] = [
* PII presets for the redact step: a label + the regex the /auto-redact endpoint
* matches (via `wordsToRedact` + `useRegex`). Patterns are precise — validated
* (SSN areas, card IINs, ABA prefixes), context- or separator-anchored — to keep
* false positives down and avoid the backtracking the old broad patterns risked.
* false positives down and avoid catastrophic backtracking.
*/
export const PII_PRESETS: { value: string; label: string; pattern: string }[] =
[
@@ -137,7 +137,7 @@ export const DEFAULT_PII_PATTERNS: string[] = [
PII_PRESETS[1].pattern, // cards
];
/** Per-category narrative + editable fields (from the prototype's POLICY_CONFIG). */
/** Per-category narrative + editable fields. */
export const POLICY_CONFIG: Record<string, PolicyConfigDef> = {
ingestion: {
summary:
@@ -149,7 +149,7 @@ export const POLICY_CONFIG: Record<string, PolicyConfigDef> = {
],
scopeLabel: "All PDFs on this device",
// Policy-level controls only — the per-tool params (OCR level, extract
// tables, naming, normalize, rotate…) now live in the Workflow step.
// tables, naming, normalize, rotate...) live in the Workflow step.
fields: [
{
label: "Min confidence",
@@ -29,13 +29,13 @@ function defaultState(): PolicyState {
// Enforce on upload by default; export enforcement is the alternative.
runOn: "upload",
// Every catalog category is a shipped, built-in policy → default (not
// deletable). User-created policies (later) will set this false.
// deletable).
isDefault: true,
};
}
/** An obsolete reviewer email from earlier development, scrubbed from persisted
* state on read so it can re-default to the real signed-in user. */
/** An obsolete reviewer email scrubbed from persisted state on read so it can
* re-default to the real signed-in user. */
const STALE_REVIEWER_EMAIL = "[email protected]";
/** Read the full policy state, seeding + healing any missing categories. */
@@ -4,9 +4,8 @@
* A Policy is conceptually like a Watch Folder (a configured automation that
* runs over documents) but backend-driven and triggered by *sources/events*
* (editor save/export, device sweeps, cloud connectors) rather than just a
* folder. Per-policy state is persisted locally (localStorage) today; server
* persistence and real enforcement land in a follow-up. Activity + stats shown
* in the detail view are derived live from the user's real uploaded files.
* folder. Per-policy state is persisted locally (localStorage). Activity + stats
* shown in the detail view are derived live from the user's real uploaded files.
*/
import type { ReactNode } from "react";
@@ -10,8 +10,8 @@
* - the per-category breakdown comes from {@code categoryBreakdown}
* (wallet_category_summary view)
* - money-equivalent display and the units↔money cap preview need
* stripe.prices via Sync Engine (design §13 / PR-C2) and are deliberately
* absent until that ships
* stripe.prices via Sync Engine and are deliberately absent until that
* ships
* - the activity feed renders {@code wallet.recent}, which is {@code []} in
* V1 — so it shows a real empty state, not fabricated rows
*/
@@ -437,10 +437,9 @@ const GATE_CAP_BEHAVIOR: { gate: Gate; staysAtCap: boolean }[] = [
];
/**
* Folded-in "what happens at the cap" — previously its own GatesCard, now a
* collapsed disclosure rendered inside the cap card(s) to save vertical space.
* Mirrors the {@link DocHelp} toggle pattern; default-collapsed so it costs no
* height until the user opens it.
* Collapsed "what happens at the cap" disclosure rendered inside the cap
* card(s) to save vertical space. Mirrors the {@link DocHelp} toggle pattern;
* default-collapsed so it costs no height until the user opens it.
*/
function CapReachedHelp() {
const { t } = useTranslation();
@@ -488,7 +487,7 @@ function CapReachedHelp() {
/**
* Leader-only roster of each teammate's billable usage this period. Display-only — per-member
* sub-cap enforcement isn't shipped (see the follow-ups note), so there's no cap control here.
* sub-cap enforcement isn't shipped, so there's no cap control here.
*/
function MemberUsage({ members }: { members: Wallet["members"] }) {
const { t } = useTranslation();
@@ -29,12 +29,12 @@
*
* Stripe-touching code lives in Supabase edge functions, not the Java
* backend. This panel invokes {@code create-checkout-session}
* directly via {@code supabase.functions.invoke()} same pattern {@link
* directly via {@code supabase.functions.invoke()} - same pattern {@link
* usePlans} already uses for {@code stripe-price-lookup}. The auth JWT is
* attached automatically by the Supabase client.
*
* <p>The edge function (SaaS PR #300) is the canonical place Stripe Checkout
* Sessions get created it uses the Stripe Sync Engine tables, has dedicated
* <p>The edge function is the canonical place Stripe Checkout
* Sessions get created - it uses the Stripe Sync Engine tables, has dedicated
* unit tests, and shares Stripe SDK / secret-key plumbing with the metering +
* webhook edge functions. Routing through Java would have meant a useless
* proxy hop + a second Stripe SDK to maintain.
@@ -170,10 +170,10 @@ const StripeCheckoutPanel: React.FC<StripeCheckoutPanelProps> = ({
// React 18 strict-mode dev mounts effects twice. We use `cancelled` to
// discard the first mount's response (its setState calls become no-ops),
// and the second mount's response wins. We deliberately do NOT short-
// circuit the second mount with a ref — earlier versions did that and
// ran into the trap where mount 1 was cancelled but the live mount
// never re-fetched, leaving `loading` stuck at true. Two network calls
// in dev is an acceptable cost; prod has no strict mode → single fetch.
// circuit the second mount with a ref: that traps mount 1 as cancelled
// while the live mount never re-fetches, leaving `loading` stuck at true.
// Two network calls in dev is an acceptable cost; prod has no strict mode
// -> single fetch.
let cancelled = false;
async function createSession() {
try {