[{"data":1,"prerenderedAt":1076},["ShallowReactive",2],{"docs-navigation":3,"\u002Fdocs\u002Fdevelopment\u002Frunbooks":231,"\u002Fdocs\u002Fdevelopment\u002Frunbooks-surround":1073},[4],{"title":5,"path":6,"stem":7,"children":8},"Docs","\u002Fdocs","docs",[9,12,16,20,69,90,123,144,165,190],{"title":10,"path":6,"stem":11},"Gerbtrace Documentation","docs\u002Findex",{"title":13,"path":14,"stem":15},"Getting Started","\u002Fdocs\u002Fgetting-started","docs\u002F1.getting-started",{"title":17,"path":18,"stem":19},"Licensing","\u002Fdocs\u002Flicensing","docs\u002F2.licensing",{"title":21,"path":22,"stem":23,"children":24,"page":68},"Viewer","\u002Fdocs\u002Fviewer","docs\u002F3.viewer",[25,29,33,37,41,45,49,53,56,60,64],{"title":26,"path":27,"stem":28},"Files","\u002Fdocs\u002Fviewer\u002Ffiles","docs\u002F3.viewer\u002F01.files",{"title":30,"path":31,"stem":32},"PCB","\u002Fdocs\u002Fviewer\u002Fpcb","docs\u002F3.viewer\u002F02.pcb",{"title":34,"path":35,"stem":36},"Panel","\u002Fdocs\u002Fviewer\u002Fpanel","docs\u002F3.viewer\u002F03.panel",{"title":38,"path":39,"stem":40},"Paste","\u002Fdocs\u002Fviewer\u002Fpaste","docs\u002F3.viewer\u002F04.paste",{"title":42,"path":43,"stem":44},"SMD","\u002Fdocs\u002Fviewer\u002Fsmd","docs\u002F3.viewer\u002F05.smd",{"title":46,"path":47,"stem":48},"THT","\u002Fdocs\u002Fviewer\u002Ftht","docs\u002F3.viewer\u002F06.tht",{"title":50,"path":51,"stem":52},"BOM","\u002Fdocs\u002Fviewer\u002Fbom","docs\u002F3.viewer\u002F07.bom",{"title":5,"path":54,"stem":55},"\u002Fdocs\u002Fviewer\u002Fdocs","docs\u002F3.viewer\u002F08.docs",{"title":57,"path":58,"stem":59},"Conversation","\u002Fdocs\u002Fviewer\u002Fconversation","docs\u002F3.viewer\u002F09.conversation",{"title":61,"path":62,"stem":63},"Summary","\u002Fdocs\u002Fviewer\u002Fsummary","docs\u002F3.viewer\u002F10.summary",{"title":65,"path":66,"stem":67},"Pricing","\u002Fdocs\u002Fviewer\u002Fpricing","docs\u002F3.viewer\u002F11.pricing",false,{"title":70,"path":71,"stem":72,"children":73,"page":68},"Tools","\u002Fdocs\u002Ftools","docs\u002F4.tools",[74,78,82,86],{"title":75,"path":76,"stem":77},"Exports","\u002Fdocs\u002Ftools\u002Fexports","docs\u002F4.tools\u002F1.exports",{"title":79,"path":80,"stem":81},"Compare","\u002Fdocs\u002Ftools\u002Fcompare","docs\u002F4.tools\u002F2.compare",{"title":83,"path":84,"stem":85},"Package Manager","\u002Fdocs\u002Ftools\u002Fpackage-manager","docs\u002F4.tools\u002F3.package-manager",{"title":87,"path":88,"stem":89},"Draw Tool","\u002Fdocs\u002Ftools\u002Fdraw-tool","docs\u002F4.tools\u002F4.draw-tool",{"title":91,"path":92,"stem":93,"children":94,"page":68},"Collaboration","\u002Fdocs\u002Fcollaboration","docs\u002F5.collaboration",[95,99,103,107,111,115,119],{"title":96,"path":97,"stem":98},"Team Settings","\u002Fdocs\u002Fcollaboration\u002Fteam-settings","docs\u002F5.collaboration\u002F1.team-settings",{"title":100,"path":101,"stem":102},"Team Members","\u002Fdocs\u002Fcollaboration\u002Fteam-members","docs\u002F5.collaboration\u002F2.team-members",{"title":104,"path":105,"stem":106},"User Profile","\u002Fdocs\u002Fcollaboration\u002Fuser-profile","docs\u002F5.collaboration\u002F3.user-profile",{"title":108,"path":109,"stem":110},"Spaces","\u002Fdocs\u002Fcollaboration\u002Fspaces","docs\u002F5.collaboration\u002F4.spaces",{"title":112,"path":113,"stem":114},"Notifications","\u002Fdocs\u002Fcollaboration\u002Fnotifications","docs\u002F5.collaboration\u002F6.notifications",{"title":116,"path":117,"stem":118},"Plans & Billing","\u002Fdocs\u002Fcollaboration\u002Fplans-and-billing","docs\u002F5.collaboration\u002F7.plans-and-billing",{"title":120,"path":121,"stem":122},"Connected Apps & MCP","\u002Fdocs\u002Fcollaboration\u002Fconnected-apps","docs\u002F5.collaboration\u002F8.connected-apps",{"title":124,"path":125,"stem":126,"children":127,"page":68},"App","\u002Fdocs\u002Fapp","docs\u002F6.app",[128,132,136,140],{"title":129,"path":130,"stem":131},"Desktop App","\u002Fdocs\u002Fapp\u002Fdesktop","docs\u002F6.app\u002F1.desktop",{"title":133,"path":134,"stem":135},"Light & Dark Mode","\u002Fdocs\u002Fapp\u002Flight-dark-mode","docs\u002F6.app\u002F2.light-dark-mode",{"title":137,"path":138,"stem":139},"Performance Monitor","\u002Fdocs\u002Fapp\u002Fperformance-monitor","docs\u002F6.app\u002F3.performance-monitor",{"title":141,"path":142,"stem":143},"Report a Bug","\u002Fdocs\u002Fapp\u002Freport-a-bug","docs\u002F6.app\u002F4.report-a-bug",{"title":145,"path":146,"stem":147,"children":148,"page":68},"Guides","\u002Fdocs\u002Fguides","docs\u002F7.guides",[149,153,157,161],{"title":150,"path":151,"stem":152},"Importing Files","\u002Fdocs\u002Fguides\u002Fimporting-files","docs\u002F7.guides\u002F1.importing-files",{"title":154,"path":155,"stem":156},"Supported Formats","\u002Fdocs\u002Fguides\u002Fsupported-formats","docs\u002F7.guides\u002F2.supported-formats",{"title":158,"path":159,"stem":160},"Package Library","\u002Fdocs\u002Fguides\u002Fpackage-library","docs\u002F7.guides\u002F3.package-library",{"title":162,"path":163,"stem":164},"Panel Checks","\u002Fdocs\u002Fguides\u002Fpanel-checks","docs\u002F7.guides\u002F4.panel-checks",{"title":166,"path":167,"stem":168,"children":169,"page":68},"Reference","\u002Fdocs\u002Freference","docs\u002F8.reference",[170,174,178,182,186],{"title":171,"path":172,"stem":173},"BOM File Format","\u002Fdocs\u002Freference\u002Fbom-format","docs\u002F8.reference\u002F1.bom-format",{"title":175,"path":176,"stem":177},"Package Definitions","\u002Fdocs\u002Freference\u002Fpackage-definitions","docs\u002F8.reference\u002F2.package-definitions",{"title":179,"path":180,"stem":181},"Package Naming","\u002Fdocs\u002Freference\u002Fpackage-naming","docs\u002F8.reference\u002F3.package-naming",{"title":183,"path":184,"stem":185},"TPSys Format","\u002Fdocs\u002Freference\u002Ftpsys-format","docs\u002F8.reference\u002F4.tpsys-format",{"title":187,"path":188,"stem":189},"Jet Printing","\u002Fdocs\u002Freference\u002Fjet-printing","docs\u002F8.reference\u002F5.jet-printing",{"title":191,"path":192,"stem":193,"children":194,"page":68},"Development","\u002Fdocs\u002Fdevelopment","docs\u002F9.development",[195,199,203,207,211,215,219,223,227],{"title":196,"path":197,"stem":198},"Development Setup","\u002Fdocs\u002Fdevelopment\u002Fsetup","docs\u002F9.development\u002F1.setup",{"title":200,"path":201,"stem":202},"Architecture","\u002Fdocs\u002Fdevelopment\u002Farchitecture","docs\u002F9.development\u002F2.architecture",{"title":204,"path":205,"stem":206},"CAD Libraries","\u002Fdocs\u002Fdevelopment\u002Fcad-libraries","docs\u002F9.development\u002F3.cad-libraries",{"title":208,"path":209,"stem":210},"Release Process","\u002Fdocs\u002Fdevelopment\u002Frelease-process","docs\u002F9.development\u002F4.release-process",{"title":212,"path":213,"stem":214},"Error Monitoring","\u002Fdocs\u002Fdevelopment\u002Ferror-monitoring","docs\u002F9.development\u002F5.error-monitoring",{"title":216,"path":217,"stem":218},"Contributing","\u002Fdocs\u002Fdevelopment\u002Fcontributing","docs\u002F9.development\u002F6.contributing",{"title":220,"path":221,"stem":222},"Commit Conventions","\u002Fdocs\u002Fdevelopment\u002Fcommit-conventions","docs\u002F9.development\u002F7.commit-conventions",{"title":224,"path":225,"stem":226},"Sidebar Design","\u002Fdocs\u002Fdevelopment\u002Fsidebar-design","docs\u002F9.development\u002F8.sidebar-design",{"title":228,"path":229,"stem":230},"Operational Runbooks","\u002Fdocs\u002Fdevelopment\u002Frunbooks","docs\u002F9.development\u002F9.runbooks",{"id":232,"title":228,"body":233,"description":1066,"extension":1067,"links":1068,"meta":1069,"navigation":1070,"path":229,"seo":1071,"stem":230,"__hash__":1072},"docs\u002Fdocs\u002F9.development\u002F9.runbooks.md",{"type":234,"value":235,"toc":1048},"minimark",[236,240,257,268,273,280,305,323,430,436,443,447,450,489,492,496,499,539,543,550,564,568,619,623,644,648,708,712,742,813,817,820,921,924,931,935,938,999,1004,1007,1011,1037,1041,1044],[237,238,228],"h1",{"id":239},"operational-runbooks",[241,242,243,244,247,248,252,253,256],"p",{},"Step-by-step procedures for operating the deployed surfaces. Companion to the\n",[245,246,208],"a",{"href":209}," (how to ship) — this page covers verifying,\nrecovering, and responding when something goes wrong. Deployment authority and\nthe edge-function operational model are defined in ",[249,250,251],"code",{},"docs\u002Fadr\u002FADR-005"," and\n",[249,254,255],{},"docs\u002Fadr\u002FADR-008",".",[258,259,260],"blockquote",{},[241,261,262,263,267],{},"Account isolation: every command here targets the ",[264,265,266],"strong",{},"Newmatik"," org only\n(Cloudflare, Supabase, Sentry). Confirm the account before acting.",[269,270,272],"h2",{"id":271},"post-deploy-verification","Post-deploy verification",[241,274,275,276,279],{},"Run immediately after a web deploy to ",[249,277,278],{},"main",":",[281,282,287],"pre",{"className":283,"code":284,"language":285,"meta":286,"style":286},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","pnpm run release:verify\n","bash","",[249,288,289],{"__ignoreMap":286},[290,291,294,298,302],"span",{"class":292,"line":293},"line",1,[290,295,297],{"class":296},"sBMFI","pnpm",[290,299,301],{"class":300},"sfazB"," run",[290,303,304],{"class":300}," release:verify\n",[241,306,307,308,311,312,315,316,315,319,322],{},"One command (",[249,309,310],{},"scripts\u002Frelease-verify.mjs","), fails closed, one line per check\n(",[249,313,314],{},"OK",", ",[249,317,318],{},"FAIL",[249,320,321],{},"SKIP","). It runs, in order:",[324,325,326,337,364,391,412],"ol",{},[327,328,329,332,333,336],"li",{},[264,330,331],{},"Synthetic probe"," — the curated public routes return 2xx\u002F3xx (the same\ncheck as ",[249,334,335],{},"pnpm run synthetic:check",").",[327,338,339,342,343,346,347,350,351,252,354,357,358,361,362,256],{},[264,340,341],{},"Deployed build"," — the Nuxt app manifest (",[249,344,345],{},"\u002F_nuxt\u002Fbuilds\u002Flatest.json","\nand ",[249,348,349],{},"\u002F_nuxt\u002Fbuilds\u002Fmeta\u002F\u003Cid>.json",", the files stale tabs poll to detect a\nnew deploy) is reachable and well-formed. The SPA is client-rendered, so\nthere is no server-rendered footer to read a version from; the build id is\nthe deploy identity. Workers Builds sets ",[249,352,353],{},"WORKERS_CI_COMMIT_SHA",[249,355,356],{},"nuxt.config.ts"," uses it as the build id, so set\n",[249,359,360],{},"RELEASE_BUILD_ID=\u003Ccommit sha>"," (short SHAs work) and the check fails unless\nthat commit is live. Unset, the comparison is reported as ",[249,363,321],{},[327,365,366,369,370,372,373,375,376,379,380,383,384,387,388,390],{},[264,367,368],{},"Docs (D1)"," — ",[249,371,6],{}," and one deep page (default\n",[249,374,229],{},", override with ",[249,377,378],{},"RELEASE_VERIFY_DOCS_PATH",")\nreturn 200 with the SPA shell, and the Nuxt Content query route\n(",[249,381,382],{},"\u002F__nuxt_content\u002Fdocs\u002Fquery",", backed by D1 in production) returns each\npage's row with its title. The first query after a deploy is what imports\n",[249,385,386],{},"dump.docs.sql"," into D1, so a ",[249,389,318],{}," here means the docs migration did not\nrun or the D1 binding is wrong.",[327,392,393,396,397,400,401,403,404,407,408,411],{},[264,394,395],{},"Sentry release"," — the same check as ",[249,398,399],{},"pnpm run sentry:verify","; ",[249,402,321],{},"\nwith a notice unless ",[249,405,406],{},"SENTRY_AUTH_TOKEN"," and ",[249,409,410],{},"SENTRY_ORG"," are set.",[327,413,414,417,418,421,422,425,426,429],{},[264,415,416],{},"Backend"," — with ",[249,419,420],{},"SUPABASE_ACCESS_TOKEN",", verify Newmatik ownership, migration versions, function\u002Fcolumn privileges, required secret metadata, gateway JWT settings, and downloaded function sources including shared dependencies. This also detects retired endpoints and probes invitation CORS without sending email. Set ",[249,423,424],{},"RELEASE_REQUIRE_BACKEND=1"," for a production gate that fails if credentials are missing. Run ",[249,427,428],{},"pnpm run backend:verify"," for the backend gate alone.",[241,431,432,433,256],{},"Target another host with\n",[249,434,435],{},"RELEASE_VERIFY_BASE_URL=https:\u002F\u002Fstaging.gerbtrace.com pnpm run release:verify",[241,437,438,439,442],{},"If the build check still reports the previous build id after a deploy, purge\ncache (",[264,440,441],{},"Cloudflare → Caching → Configuration → Purge Everything",") and re-run.",[269,444,446],{"id":445},"web-app-rollback-cloudflare-workers","Web app rollback (Cloudflare Workers)",[241,448,449],{},"The web app deploys via Cloudflare Workers Builds (ADR-005). To roll back:",[324,451,452,458,461,468,479],{},[327,453,454,455,256],{},"Open ",[264,456,457],{},"Cloudflare → Workers & Pages → gerbtrace → Deployments",[327,459,460],{},"Identify the last known-good deployment (match the commit SHA \u002F version).",[327,462,463,464,467],{},"Use ",[264,465,466],{},"Rollback"," to promote it, or re-run the build for the good commit.",[327,469,470,471,474,475,478],{},"Re-run ",[249,472,473],{},"pnpm run release:verify"," with ",[249,476,477],{},"RELEASE_BUILD_ID"," set to the\nknown-good commit so the build check proves the rollback is live.",[327,480,481,482,485,486,488],{},"If the bad build shipped a D1 docs migration, the docs check in\n",[249,483,484],{},"release:verify"," covers it; the docs table is rebuilt from ",[249,487,386],{},"\non each deploy, so rolling the Worker back also restores the previous docs\nsnapshot.",[241,490,491],{},"Never hand-edit production Worker code outside the build pipeline.",[269,493,495],{"id":494},"supabase-incident-migration-recovery","Supabase incident \u002F migration recovery",[241,497,498],{},"Migrations are applied to Supabase Cloud (ADR-001\u002F003). If a migration causes an\nincident:",[324,500,501,504,515,522,536],{},[327,502,503],{},"Stop further deploys.",[327,505,506,507,510,511,514],{},"Diagnose with ",[249,508,509],{},"get_logs"," \u002F ",[249,512,513],{},"get_advisors"," (Supabase MCP) before changing\nanything.",[327,516,517,518,521],{},"Because migrations are idempotent and additive, prefer a ",[264,519,520],{},"forward fix",": a\nnew idempotent migration that corrects the schema, rather than a destructive\nrollback.",[327,523,524,525,528,529,532,533,256],{},"For a bad column default or policy, ship a corrective ",[249,526,527],{},"CREATE OR REPLACE"," \u002F\n",[249,530,531],{},"ALTER ... IF EXISTS"," migration and re-run ",[249,534,535],{},"pnpm run migrations:check",[327,537,538],{},"Treat production data as off-limits for destructive statements without\nexplicit approval.",[269,540,542],{"id":541},"edge-function-rollback","Edge Function rollback",[241,544,545,546,549],{},"Edge Functions share auth and timeout helpers (",[249,547,548],{},"supabase\u002Ffunctions\u002F_shared\u002F",",\nADR-008) and return the real Supabase error message.",[324,551,552,555,558],{},[327,553,554],{},"Redeploy the previous known-good function from the last good commit\n(Supabase dashboard or CLI).",[327,556,557],{},"Confirm the function returns the expected error surface (not a hardcoded\nstring) via a probe request.",[327,559,560,561,563],{},"Check ",[249,562,509],{}," for the function to confirm the error rate returns to\nbaseline.",[269,565,567],{"id":566},"incident-response-quick-path","Incident response (quick path)",[324,569,570,576,594,600,613],{},[327,571,572,575],{},[264,573,574],{},"Confirm scope"," — is it web, desktop, API, or docs? Use the synthetic\ncheck and Sentry to localize.",[327,577,578,581,582,585,586,589,590,593],{},[264,579,580],{},"Filter noise"," — in Sentry, split production (",[249,583,584],{},"www.gerbtrace.com",") from\n",[249,587,588],{},"localhost","\u002Ffeature-branch noise via the ",[249,591,592],{},"url"," tag; ignore the known\nbot\u002Fold-browser patterns.",[327,595,596,599],{},[264,597,598],{},"Mitigate"," — roll back the affected surface (sections above).",[327,601,602,605,606,608,609,612],{},[264,603,604],{},"Verify"," — re-run ",[249,607,473],{}," (or ",[249,610,611],{},"synthetic:check"," for a\nquick route probe); watch Sentry error rate.",[327,614,615,618],{},[264,616,617],{},"Follow up"," — add a Vitest regression first when possible, then a browser\nsmoke check only if the failure needs the browser (ADR-007).",[269,620,622],{"id":621},"synthetic-checks","Synthetic checks",[624,625,626,631,637],"ul",{},[327,627,628,629,256],{},"Manual: ",[249,630,335],{},[327,632,633,634,256],{},"Custom target: ",[249,635,636],{},"SYNTHETIC_BASE_URL=https:\u002F\u002Fstaging.gerbtrace.com pnpm run synthetic:check",[327,638,639,640,643],{},"Scheduled: ",[249,641,642],{},".github\u002Fworkflows\u002Fsynthetic.yml"," runs the check on a cron and can\nbe triggered manually from the Actions tab.",[269,645,647],{"id":646},"sentry-release-verification","Sentry release verification",[624,649,650,671,686],{},[327,651,652,654,655,657,658,252,660,662,663,666,667,670],{},[249,653,473],{}," runs this check as its last step; run\n",[249,656,399],{}," on its own with ",[249,659,406],{},[249,661,410],{}," set (optionally ",[249,664,665],{},"SENTRY_RELEASE",", else the ",[249,668,669],{},"package.json","\nversion).",[327,672,673,674,677,678,681,682,685],{},"The build plugin uploads debug-ID artifact bundles, not legacy release\nfiles. The check loads the deployed site (",[249,675,676],{},"RELEASE_VERIFY_BASE_URL",", default\nproduction), reads the Sentry debug ID injected into each entry chunk, and\nasks Sentry's artifact lookup for it (",[249,679,680],{},"SENTRY_PROJECT",", default\n",[249,683,684],{},"gerbtrace","). It then reads the matching bundle's manifest, because a bundle\ncan hold the minified file without its source map.",[327,687,688,689,692,693,695,696,699,700,703,704,707],{},"It fails if the release is missing, a checked chunk carries no debug ID, or\nany checked chunk has no uploaded source map, meaning production stack\ntraces would not symbolicate. The upload runs only in Workers Builds (",[249,690,691],{},"CI"," set) and\nneeds the ",[249,694,406],{}," build secret on the ",[264,697,698],{},"Deploy default branch","\ntrigger (Workers & Pages → gerbtrace → Settings → Build → Variables). Use a\nNewmatik org auth token (",[249,701,702],{},"org:ci"," scope), then redeploy. The build log line\n",[249,705,706],{},"No auth token provided. Will not upload source maps"," means it is missing.",[269,709,711],{"id":710},"elexess-integration","Elexess integration",[241,713,714,715,718,719,722,723,726,727,730,731,734,735,315,738,741],{},"BOM pricing searches go through ",[249,716,717],{},"main\u002Felexess-search"," to the Elexess REST API (",[249,720,721],{},"https:\u002F\u002Fapi.elexess.com\u002Ffunctions\u002Fv1",", override with the ",[249,724,725],{},"ELEXESS_URL"," Edge Function secret). It authenticates with an Elexess ",[264,728,729],{},"team API token"," (",[249,732,733],{},"el_live_...","). The platform-wide token is set in Admin → Platform Settings, and a team-specific override in Admin → Teams → Integrations. Both are stored service-role only (",[249,736,737],{},"platform_config",[249,739,740],{},"team_integration_secrets",") and shown masked to their first 12 characters.",[624,743,744,751,761,784,787,794],{},[327,745,746,747,750],{},"The production platform token is ",[249,748,749],{},"gerbtrace-production-donotdelete"," on the Newmatik Elexess team (Elexess → Dashboard → API Tokens). Revoking it stops all Gerbtrace pricing searches.",[327,752,753,756,757,760],{},[264,754,755],{},"Test Connection"," calls the quota-free ",[249,758,759],{},"\u002Fsuppliers"," endpoint. Each search spends one credit of the token's Elexess team.",[327,762,763,764,315,767,315,770,773,774,510,777,510,780,783],{},"The Edge Function maps REST results (",[249,765,766],{},"stock",[249,768,769],{},"lead_time",[249,771,772],{},"prices",") onto the ",[249,775,776],{},"current_stock",[249,778,779],{},"current_leadtime",[249,781,782],{},"pricebreaks"," shape stored in project pricing caches, so existing caches stay readable.",[327,785,786],{},"Errors: a rejected token returns 503 (\"Contact your administrator\"), an exhausted Elexess quota returns 429, and an outage across all suppliers returns 503.",[327,788,789,790,793],{},"The retired Basic-auth API (",[249,791,792],{},"api.dev.elexess.com",") no longer resolves. The one team's migrated username\u002Fpassword were deleted on 2026-09-30. Setting or clearing a team token in the admin UI also removes such values.",[327,795,796,799,800,803,804,315,806,407,809,812],{},[264,797,798],{},"Rollout order"," for ",[249,801,802],{},"20260928150000_team_integration_secrets.sql",": apply the migration first, then immediately deploy ",[249,805,278],{},[249,807,808],{},"admin-team-action",[249,810,811],{},"admin-usage",". Between the two steps, older functions see no team keys: Spark runs fall back to the platform key and admin pages show \"Global\". New functions deployed before the migration fail closed.",[269,814,816],{"id":815},"security-and-billing-remediation-rollout","Security and billing remediation rollout",[241,818,819],{},"These changes require a coordinated backend deployment before the frontend. Do not roll the database permissions back to restore an older app. Use forward migrations for database fixes.",[324,821,822,836,859,872,911,914],{},[327,823,824,825,407,828,831,832,835],{},"In an isolated local Supabase project, apply all migrations and run ",[249,826,827],{},"supabase test db",[249,829,830],{},"pnpm run test:account:local",". The account integration runner accepts only local API\u002Fdatabase URLs, creates disposable users\u002Fteam\u002Ffile fixtures, verifies preserved bytes, and cleans up its fixtures. It supplies the local service-role table grants missing from recent CLI bootstrap images. Replay the three ",[249,833,834],{},"20260928"," remediation migrations in timestamp order and rerun the tests. Run typecheck, unit tests, Deno checks\u002Ftests, browser smoke, and a Worker build.",[327,837,838,839,842,843,846,847,850,851,854,855,858],{},"Prepare a ",[264,840,841],{},"dedicated Gerbtrace portal configuration"," in Stripe test mode first, then in production during the approved rollout. Enable subscription updates with exactly the Pro and Team prices, ",[249,844,845],{},"proration_behavior=always_invoice",", and ",[249,848,849],{},"billing_cycle_anchor=unchanged",". Enable cancellation with ",[249,852,853],{},"mode=at_period_end",". Enable payment-method updates, invoice history, and customer name\u002Femail\u002Faddress\u002Ftax-ID updates. Ensure downgrade scheduling matches the published billing terms. Set its ID as the Edge Function secret ",[249,856,857],{},"STRIPE_PORTAL_CONFIGURATION_ID",". Never change the shared default portal for the other products on this Stripe account.",[327,860,861,862,315,865,846,868,871],{},"Apply ",[249,863,864],{},"20260928130000_harden_team_and_account_access.sql",[249,866,867],{},"20260928131000_atomic_billing_reconciliation.sql",[249,869,870],{},"20260928132000_fix_checkout_reservations.sql"," in timestamp order. ACL\u002Fownership failures abort the migration: have the function owner apply the ACL changes rather than skipping them. Regenerate database types from the updated schema. The first migration seeds no memberships for unverified addresses; the billing migration preserves existing granted tiers as a baseline. Review previously suspicious memberships, customer associations, and duplicate subscriptions separately before authorizing any cleanup.",[327,873,874,875,315,878,315,881,315,884,315,887,846,890,892,893,896,897,899,900,903,904,906,907,910],{},"Deploy ",[249,876,877],{},"stripe-checkout",[249,879,880],{},"stripe-portal",[249,882,883],{},"stripe-webhook",[249,885,886],{},"send-invitation",[249,888,889],{},"delete-account",[249,891,808],{}," from this commit, using the gateway settings in ",[249,894,895],{},"supabase\u002Fconfig.toml",". Deploy ",[249,898,278],{}," to remove its old duplicate handlers. Redeploy any other function whose downloaded dependency differs from git. The retired ",[249,901,902],{},"handle-team-join"," endpoint was deleted on 2026-09-28 after 30 days of edge logs showed no callers (ADR-001). ",[249,905,895],{}," declares ",[249,908,909],{},"verify_jwt"," for every function; the backend gate fails on an undeclared or differing gateway setting, and on any deployed function without source in git. These operations require the separately approved production rollout.",[327,912,913],{},"Merge\u002Fpush the frontend changes for Cloudflare Workers Builds. Desktop builds use the same plan enum requests and no longer depend on public Stripe price IDs.",[327,915,916,917,920],{},"Run ",[249,918,919],{},"RELEASE_REQUIRE_BACKEND=1 RELEASE_BUILD_ID=\u003Ccommit> pnpm run release:verify"," with Newmatik credentials. Inspect Stripe webhook retries, function errors, and Sentry after deployment. Do not use a live card payment, send a real invitation\u002Ffeedback message, or delete a production account as a verification probe.",[241,922,923],{},"Stripe reconciliation reads the latest customer subscription list, filters to Gerbtrace prices, and commits subscriptions, the granted plan, billing details, and the event receipt in one transaction. A generation check rejects overlapping stale snapshots so Stripe retries. Failed renewals retain the last granted tier; unpaid upgrades cannot grant a higher tier. Foreign prices are never persisted as Gerbtrace prices. A team deletion records its intent and blocks new checkout reservations before canceling all associated Gerbtrace subscriptions; a pending checkout lease delays deletion for up to 45 minutes. Failed cancellations or team deletes preserve the team and release the deletion marker for retry. Successful deletions retain their tombstone. Only new Checkout sessions acquire a lease. A fresh lease gives session creation five minutes of headroom above Stripe's minimum lifetime; late retries recover an existing session by its request metadata or return a conflict until the lease expires without changing the idempotent payload.",[241,925,926,927,930],{},"For support verification, use mocked SDK transport acceptance\u002Frejection and Help Scout identity\u002Fconsent tests locally. In a separately authorized staging check, confirm an actual feedback item and support conversation reach the Newmatik destinations. A Sentry event ID alone is not a delivery acknowledgement. Bug report drafts survive unconfirmed delivery; the Contact Support menu falls back to ",[249,928,929],{},"software@newmatik.com"," if Beacon fails to load.",[269,932,934],{"id":933},"project-access-and-enrolled-mfa-rollout-2026-10-01","Project access and enrolled-MFA rollout (2026-10-01)",[241,936,937],{},"This is a release procedure, not an automatic migration step. Confirm the\nNewmatik Supabase organization\u002Fproject and Cloudflare account before invoking\nexternal services. The implementation has only been exercised against an\nisolated local database; production remains unchanged.",[324,939,940,955,969,990,993,996],{},[327,941,942,943,946,947,950,951,954],{},"Check existing ",[249,944,945],{},"authenticator"," role configuration for a\n",[249,948,949],{},"pgrst.db_pre_request"," hook. The MFA migration deliberately refuses to replace\nan unrelated hook. Compose the existing hook with\n",[249,952,953],{},"public.require_mfa_assurance"," in a reviewed migration if necessary.",[327,956,861,957,960,961,964,965,968],{},[249,958,959],{},"20261001090000_align_space_and_bom_access.sql",", then\n",[249,962,963],{},"20261001091000_enforce_enrolled_mfa.sql",". Replay both on staging and run the\ndatabase tests. Subsequent migrations that add RLS tables must also add the\nrestrictive ",[249,966,967],{},"enrolled_mfa"," policy; the database regression detects omissions.",[327,970,971,972,975,976,315,978,315,980,982,983,985,986,989],{},"Redeploy all Edge Functions from the approved commit, including ",[249,973,974],{},"mcp",",\n",[249,977,278],{},[249,979,886],{},[249,981,889],{},", the admin functions and Stripe\nfunctions, because their shared authorization dependency changed. Use the\ngateway configuration in ",[249,984,895],{},"; MCP remains\n",[249,987,988],{},"verify_jwt = false"," with caller-token authorization inside the handler.",[327,991,992],{},"Verify unenrolled AAL1 sign-in still works. For an enrolled test account,\nverify AAL1 cannot read\u002Fupdate account data or invoke privileged functions,\nthen challenge to AAL2 and verify access resumes. Exercise recovery,\nfactor removal and an OAuth\u002FMCP return path. Do not alter production users\nfor testing. An enrolled caller whose OAuth token is AAL1 must establish an\nAAL2 session before MCP tools work.",[327,994,995],{},"Verify editor\u002Fviewer\u002Fguest storage and BOM access, including assigned and\nunassigned spaces. Inactive space members must lose access; storage access\nuses the actual team\u002Fproject path and project authorization.",[327,997,998],{},"Deploy the Worker and run the post-deploy gate for the exact commit, docs\nD1 delivery and Sentry source maps. Desktop releases run the complete shared\nCI gate before signing. Keep deployment rollback tied to the approved\nprevious frontend\u002Ffunction release; removing the MFA gate is a separate\nsecurity decision, not an automatic incident workaround.",[1000,1001,1003],"h3",{"id":1002},"persistence-upgrade","Persistence upgrade",[241,1005,1006],{},"The outbox database gains account\u002Fproject keys. Legacy rows stay in the\noriginal table as an unclaimed quarantine; they are never replayed by the next\naccount. Do not delete or assign these rows automatically. If a user reports\nlegacy unsaved work, recover it only after verifying ownership. New storage\nfailures remain visible and keep unsaved edits in memory; users should keep the\nproject open while retrying.",[1000,1008,1010],{"id":1009},"public-html-and-image-delivery","Public HTML and image delivery",[241,1012,1013,1016,1017,1020,1021,1024,1025,1028,1029,1032,1033,1036],{},[249,1014,1015],{},"pnpm run build"," prerenders the public inventory and retains the Worker\u002FD1\narchitecture. Run ",[249,1018,1019],{},"node scripts\u002Fcheck-public-html.mjs"," after the build. Verify\nan actual public document without JavaScript, and confirm application routes\nstill require sign-in. ",[249,1022,1023],{},"pnpm run generate"," sets ",[249,1026,1027],{},"NUXT_DESKTOP=1"," and produces\nthe desktop SPA. Keep the ",[249,1030,1031],{},"\u002Fdump.docs.sql"," redirect in both configurations.\nRegenerate documentation WebP variants with ",[249,1034,1035],{},"pnpm run docs:images"," after\nchanging source screenshots; the full PNG remains the enlarged view.",[1000,1038,1040],{"id":1039},"machine-program-acceptance","Machine-program acceptance",[241,1042,1043],{},"The deterministic JPSys tests and reference snapshot are necessary release\nchecks. Before shipping the machine-program changes, validate the supplied\nreference export in JPSys on the target machine profile and perform the normal\nsimulation\u002Fdry-run procedure. Record the software\u002Fmachine profile and expected\norientation, fiducials, volume and dot path. This local implementation has not\nrun a physical machine or a production printing job.",[1045,1046,1047],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":286,"searchDepth":1049,"depth":1050,"links":1051},3,2,[1052,1053,1054,1055,1056,1057,1058,1059,1060,1061],{"id":271,"depth":1050,"text":272},{"id":445,"depth":1050,"text":446},{"id":494,"depth":1050,"text":495},{"id":541,"depth":1050,"text":542},{"id":566,"depth":1050,"text":567},{"id":621,"depth":1050,"text":622},{"id":646,"depth":1050,"text":647},{"id":710,"depth":1050,"text":711},{"id":815,"depth":1050,"text":816},{"id":933,"depth":1050,"text":934,"children":1062},[1063,1064,1065],{"id":1002,"depth":1049,"text":1003},{"id":1009,"depth":1049,"text":1010},{"id":1039,"depth":1049,"text":1040},"Post-deploy release verification, rollback, incident response, synthetic checks, and Sentry release verification for the deployed surfaces.","md",null,{},true,{"title":228,"description":1066},"CIo6U7YvHLzKbMozUK3EURrzQLbUGARLHNXmj5YcTHg",[1074,1068],{"title":224,"path":225,"stem":226,"description":1075,"children":-1},"Reusable sidebar UX pattern used in the panel editor and other screens.",1790998747457]