Patent
Patent (registry slug patent-exclusivity, segment /patent) shows the patents and exclusivities recorded in its captured FDA files for a US product, each date with the rule it rests on and the row it came from, as a range of listed protection rather than one date; candidate ANDA matches for the same ingredient and dosage form; the Paragraph IV list's row; the Purple Book's dates for biologics; a date window; and what changed in the FDA's files between captures. It reads one static store built from the files the daily capture keeps (Stage I-0, Data pipeline); nothing is fetched from the FDA in the browser. Decided as Stage I of the v0 depth roadmap on 13 October 2026 (D-0077); named Patent (D-0078); the design brief is docs/design/brief-patent.md and the architecture record docs/design/patent-stage/architecture.md.
Purpose and users
The app answers "when does this US product's listed protection end, by which rule, and what else is listed?" (research 7.4 question 10). The registry describes it as "Listed patents and exclusivities for a US product, each date traced to its Orange Book or Purple Book rule." Intended users, from the brief (intent, not measured): generics and biosimilar business-development staff, biotech BD, CI and portfolio staff without a database seat, boutique consultancies, investors and analysts, and students of regulatory affairs.
What it is not, as the registry's limits state (content/tools/patent-exclusivity.ts, detail.limits): not a loss-of-exclusivity date (litigation, settlements, patent term extensions, unlisted patents, at-risk launches, authorised generics and 505(b)(2) products are not in these files); not legal, regulatory or investment advice; not a patent search (no full text, claims, families or non-US coverage). The only arithmetic is NCE-1; the pediatric six months is shown only where the FDA lists it.
Status, version and governing decisions
| Item | Value | Where |
|---|---|---|
| Product name | "Drybench Patent", short "Patent" | content/app-names.ts |
| Status and version | status: "alpha", version: "0.2.0", updated: "2026-10-18" |
content/apps/patent-exclusivity.ts |
| Accent and mark | plum (shared with Assay; never adjacent), shield |
content/apps/identity.ts, src/components/suite/mark.tsx |
| Workspace group and registry position | literature (D-0079): the rail shows its tile directly under Literature, in Literature's box; registry index four, after Cell, so the launch four keep their hues | content/apps/identity.ts, content/apps.ts |
| Workers, WebGL, share-alike data | all false |
entry.flags |
| Statements | not medical, investment or regulatory advice; forecasts | entry.statements |
Decisions that shape the app: D-0077 (the stage, the capture, the placement as the tenth registry app, the two-dates rule, the free/paid line), D-0078 (the name, slug and segment), the five seat memos of 13 October 2026 under docs/board/memos/ (the rules R1 to R7 are the CSO's; the views and the free/paid line the CPO's; the capture and the store the CTO's; the kill terms the CFO's; the copy rules the CMO's), and the shell decisions every app follows (Shared shell).
Addresses and entry points
| Address | What it serves |
|---|---|
/patent |
The product page (marketing route, registry copy in content/apps/patent-exclusivity.ts page) |
/patent/app |
The workspace (src/apps/patent-exclusivity/entry.tsx, loaded by src/apps/definitions.ts only on this app's route) |
/patent/app#s=... |
The workspace with state in the fragment (see below) |
/patent/app?application=NDA202155 |
The inbound deep link, rewritten to the fragment on arrival; ?name= opens the search with that text |
/docs/patent |
The docs page (content/apps/patent-exclusivity.docs.ts) |
No task pages or explainers ship yet; the CMO's list (brief §11.3) is Stage I-2's public-page work.
File map
| Path | What it holds |
|---|---|
content/apps/patent-exclusivity.ts, .entry.ts, .workspace.ts, .docs.ts, .objects.ts; content/tools/patent-exclusivity.ts; content/apps/changelog/patent-exclusivity.ts |
The registry entry, every word the app shows, the docs page, the write-up, sources and limits, the changelog |
src/lib/exclusivity/ |
The engine: types.ts (the records and the trace), dates.ts, parse.ts (the five header-driven parsers and parseStore), index.ts (the join into applications, the names index, generics), trace.ts (traceProtection, R1 to R7, the summary set, NCE-1, expiringWithin), store-manifest.ts (generated: the shipped store's path, hash and kind) |
src/apps/patent-exclusivity/ |
definition.ts, entry.tsx, url-schema.ts, store.ts, objects.ts, object-tabs.ts, object-tab.tsx, data.ts (the store loader), exports.ts, inspector.tsx, workspace.tsx and views/ |
pipeline/patent-exclusivity/ |
capture.py (the daily capture), build-store.py (packs the capture's text, or the synthetic fixture's), build-served.mts (the served store: the engine at build time, the ceilings, the manifest), trace_reference.py (the Python second implementation), fixtures/synthetic/ (invented rows in the FDA file layouts, with expected.json), the README |
public/data/patent-exclusivity/ |
The served store (REL-197): meta.<hash>.json, index.<hash>.json, the shards sNN.<hash>.json and changes.<hash>.json, content-hashed, one immutable cache rule; named by src/lib/exclusivity/store-manifest.ts |
.github/workflows/capture-patent.yml; the capture-watchdog job in scheduled.yml |
The capture and its watchdog (Build, test and CI) |
scripts/size-budgets/patent-exclusivity.json |
The definition and workspace chunk budgets |
e2e/patent-exclusivity/ |
The browser tests on the shipped store |
Workspace structure
Nothing open: the shared discovery start (the mark, one sentence, the search over the store's names, the examples from the store, the privacy line) and a second entrance to the date window. A product open: the shared discovery header (the search, the product's name and ingredient as the H1, its application number, product count and applicant as listed, the capture-date chip and the product's object actions), a synthetic-store notice for example stores or an explicit independent-review-pending notice for captured stores, the section tabs Protection, Patents, Exclusivity, Generics and Paragraph IV, Changes, and the view region; the advice line last. The date window is its own view, reachable without a product. The inspector shows one row's or one date's citations and the links elsewhere (the ingredient in Molecule). The rail lists the views with their counts and the examples.
State in the address
#s= keys under src/apps/patent-exclusivity/url-schema.ts, all public identifiers or choices: application (the open application as openFDA writes it, "NDA202155"; the subject; the same key as the hand-off dictionary's, so ?application= is accepted as it is and rewritten to the fragment on arrival), view (one of protection, patents, exclusivity, generics, changes, window; absent for Protection), from and to (the window's ISO days; the next twelve months until set), src (the Changes view's file filter), row (the row or rule date open in the inspector: d: a rule date's id, r: a file and line), name (a hand-off's text, the dictionary's name key: the first product the index finds opens and the key leaves the address; a name the store does not know stays and the start says so). Nothing a person authored travels in a link. The product page's live preview keeps its state in memory and opens on the example.
Data flow
capture-patent.ymlrunscapture.pydaily and commits normalised text, keyed diffs and a heartbeat to the orphan branchdata/exclusivity(Data pipeline).node pipeline/patent-exclusivity/build-served.mts --data-dir <checkout> --commit <sha>runsbuild-store.pyto pack the branch'scurrent/text with each file's capture record, then runs the engine at build time over the whole store (src/lib/exclusivity/served.ts,buildServed): the Paragraph IV join by exactly one isolated 4–6 digit token, padded to six digits, to an N-type application with product rows; unresolved rows remain separately readable, the ANDA join and every application's rule dates. It writes a meta file (kind, build time, sources, the FDA's code list, the parse notes), a names-and-dates index (each rule date's rule, day, subject, products, marked flags and first row; the engine rebuilds its title and definition) and up to 100 shards by application number modulo 100 (each row as the FDA's text line with its line number; for an NDA, its generics' product lines), refuses any file over its ceiling (the index 350 KiB, a shard 50 KiB, metadata 8 KiB and changes 256 KiB gzipped), and writes the manifest.--syntheticbuilds the example store the same way.- The workspace fetches the meta file and the index once per session (
src/apps/patent-exclusivity/data.ts, plain same-originfetch) and makes the catalog (makeCatalog: the names search, the labels, the date window withpastset for the day the page is read); opening a product fetches its one shard and parses its lines with the same parsers (readShardApp), keeping each row's line in the file, then traces it in the browser (traceProtection, with the meta file's code list). The object-page tab reads the meta file and the one shard only.
No host is contacted beyond the site itself; the registry declares no endpoint and the CSP gains nothing.
Science and analytics
The seven rules (the CSO's memo of 13 October 2026 §A; the docs page's "The seven rules"): R1 a listed patent's expiry as submitted with its substance, product and use flags; R2 the *PED row as the FDA lists it, never six months added; the FDA lists a *PED row without flags, so it reads the substance and product flags of its base rows (same application, product number and patent number, never across products) when they agree, marked as taken from them on screen, in the inspector (with the base rows' citations) and in both CSV exports, and stays unflagged with a note when no base row exists or the base rows disagree (SCI-125, fixed; the CSO's ruling of 14 October 2026); R3 each exclusivity code and date with the FDA's definition, an unknown code rendered as such; R4 NCE-1, the one computation; R5 the Paragraph IV row as listed, never "no Paragraph IV" from absence; R6 the generics for the ingredient and dosage form from the products file (the Drugs@FDA join for tentative approvals is a later ruling); R7 delist-requested and use-code patents kept and flagged. The summary is a set: the latest substance patent, the latest listed patent of any kind, the latest exclusivity, and the earliest and latest of every rule's dates. Dates the FDA wrote in words ("Approved Prior to Jan 1, 1982") keep their text with a null ISO date and a note. The Paragraph IV list arrives as an XLSX, which leaves empty cells out; the capture (pipeline/patent-exclusivity/capture.py, xlsx_to_text) places each cell by its column reference and marks the text textFrom: "xlsx-cells-by-reference-v1" in its capture record, which build-store.py carries into the store's sources (REL-229). An XLSX capture without the mark read cells by their order, so after an empty cell every value slid left (on the capture of 14 October 2026, 793 of 1,650 rows): parsePiv then places only a short row's drug name, keeps its other cells as unplaced (shown as captured, never under a column) and the index joins it to no application; a full-width row is read as usual (pivCellsPlaced; a shard built from such a store carries pivColumns: "unplaced"). Spreadsheet dates are 1900-system serials (the workbook sets no date1904). The table shows FDA's cells as given: a blank is FDA's blank, and the last qualifying patent expiry is FDA's figure, not recomputed from the Orange Book (the CSO's ruling of 17 October 2026). The reference pages' subset content/seo/data/incretin-fda.json had its Paragraph IV text re-derived from the same spreadsheet (sha256 unchanged) by pipeline/seo-reference/regenerate-piv-text.py; pipeline/seo-reference/patent-reference.test.ts checks its Ozempic rows. The parsers are header-driven and record every expected column they did not find in Store.notes, which the limits show.
Provenance and limits
Every date on screen carries a RowRef (file, line, key) and the store's per-source capture record; the capture-date chip names the files' capture; exports carry the same citations per row and the limits in a README. The limits panel carries the listing-accuracy line, the range-not-LOE line, the Paragraph IV completeness line, the Purple Book blanks line, the first-capture line and, while it applies, the synthetic-store line.
Objects, Studies and hand-off
Patent owns no type. It reads product (a product sent to it opens by the first application number of its fda: ref) and writes product (an application opened in the workspace is learned as Pipeline's product with one facts block from the capture: patents listed, exclusivities listed and the three summary dates; an unknown source data-as-of date stays absent) and declares the tab "Patents and exclusivity" on a product's page. Outbound: the ingredient's name to Molecule (the L3 pattern); a link to Pipeline waits for Pipeline's search by product. The watchlist (mine:watch) is Stage I-3's and is not here.
Exports
CSV per view with a citation per row (file, line, key, file date, capture date, checksum), the capture record of every source and the limits in the README; the synthetic-store line in capitals while it applies. No figure export.
Methods and checks dialog
The methods and checks dialog (D-0085; Shared shell, Registry and content) reads content/apps/patent-exclusivity.methods-sheet.ts: one group per view, quoting the docs page's rules (R1 to R7, the summary, the store) and test entries; the join is the app-wide check. No view has a method record or a level. definition.methods.group() returns the store's view.
Verification
src/lib/exclusivity/*.test.ts (the parsers, each rule including the negative control, the summary, NCE-1, the window; the engine against the Python second implementation's expected.json); pipeline/patent-exclusivity/capture.test.ts (the capture's self-test); the store file named by the manifest parses and has a known kind; the registry tests; the browser tests under e2e/patent-exclusivity/. The release gates (docs/roadmap-v0-depth.md Stage I exit criteria): the real Eliquis fixture F1 from the FDA's file of a stated date, the Q-19 reviewer's signature on F1 to F7, and the capture running with no unexplained gap.
Known gaps, defects and divergences
- The candidate store is the pinned real FDA capture; independent rule/fixture review is pending (SCI-124).
- Headers and row preservation are mechanically checked against the pinned capture; source updates require a newly reviewed input manifest.
- No tentative-approval join (R6 from Drugs@FDA), no company-disclosed date column (Column B needs a curated set), no task pages or explainers, no watch or digest (I-3), a restored alpha landing listing with explicit independent-review-pending copy.
- The Patent tab on Pipeline's product page reads the store on open; a product the store does not hold shows a plain "not in the capture" line.
Extending and refreshing safely
A new rule is a change to trace.ts with a fixture row that exercises it, a case in the Python reference and a new write-once expected-output version, a methods entry in the docs page and this page's rule list. A new source is a capture change (capture.py SOURCES), a parser in parse.ts with its notes, a registry source with its licence line, and the data-sources page. Refreshing the store is build-store.py --data-dir on a checkout of data/exclusivity, then npm test and a pull request; never a hand edit of the store or the manifest.
Public reference workflows (16 October 2026)
The public incretin route receives a native-format subset of the September 2026 FDA Orange Book capture. Original row references are retained; no synthetic rows or fabricated change history are added. The ordinary Patent store now also serves the pinned real capture described above. See Public reference workflows for the shared route, state, source and export contracts.
Captured-source corrections (18 October 2026)
The independent source-first reference at
pipeline/patent-exclusivity/fixtures/capture-2026-10-17/reference-1.json
was committed before the engine changes. It retains 439 source rows, original
coordinates and both semantic and historical capture keys, with 30 application
summaries. reference-capture.test.ts compares all supported dated facts and
summaries, PIV attribution and served-file round trips. The offline Python
excerpt check re-reads the retained rows and compares both independent and
established Python summaries; the full-capture check additionally verifies
selection completeness against the pinned archive. These are mechanical
checks, with independent regulatory review still pending (SCI-124). F4, F6
and F7 have explicit unavailable manifests; they are not passed fixtures.
SCI-228 adds the Purple Book's reference-product exclusivity expiry as a distinct subject. SCI-229 retains supplied non-date text such as Date TBD in the table and CSV and excludes it from numeric date ranges; the blank notice considers all four expiry columns. SCI-230 removes name-prefix and wrong-type PIV attribution. The 76 unresolved captured rows remain available as raw source lines with their header and original coordinates, never as evidence for the open product. ANDA candidates remain ingredient/form matches, not a therapeutic-equivalence conclusion; tentative approvals are unavailable. SCI-231 separates source dates (unknown here), capture time, last successful check and build time. Undated code definitions remain undated and qualified.
Exports distinguish the raw download SHA-256 from each normalised member's SHA-256. Purple expiry exports include all four source columns, retaining blanks and non-date text. The Changes view carries excluded initial-capture and normalisation-correction receipts; these do not count as FDA listing changes. The captured store's review-pending notice appears in workspace, product-object tab and export README.
The 18 October officer follow-up (SCI-236/237) retains all five PIV date
texts beside parsed ISO dates, including Pre-MMA; unplaced legacy cells
remain unplaced. CSV carries separate raw-text columns. Protection, citation
lookup and export row collections read trace.dates once: nce1 points to
the latest R4 for summary use and is not appended again. Withheld PIV rows
carry per-row refusal reasons. The full-store test reconstructs each original
member from unique, complete source coordinates and compares bytes and
SHA-256, excluding secondary generic copies from primary accounting.
The 0.2.0 real examples are NDA202155 (Eliquis), BLA125057 (Humira),
NDA204629 (Jardiance) and ANDA210180 (Apixaban, Accord Healthcare).
The landing listing omits the registry's opt-out-only landing: false flag;
included apps have no flag. It retains export version 3 and the existing shape.
A prior synthetic poster remains explicitly labelled synthetic until replaced.
No weekly store-refresh guarantee is made.
Loose CSV deliveries now include the provenance JSON and README so source receipts, review-pending status and candidate-match qualifications travel with the table. The shared export writer and delivery policy are unchanged.
The CPO's final source review corrected aggregate provenance to explicitly label the latest capture and list per-source dates, respecting source filters. CSV evidence-status columns and provenance limits carry review-pending status independently of the README. Window export reopens each relevant application through the existing shard cache and recovers full inherited-flag/base-row receipts before writing; unavailable or inconsistent source rows refuse the whole export. Candidate ANDA wording is consistent in table counts and empty states; methods identify tentative approvals as unavailable.
The Patent search suggestion popup anchors below the complete controls row.
At phone widths the input remains full width and suggestions do not cover Open
(CPO memo 2026-10-18-cpo-patent-store-phone-search.md, REL-374).
Window exports carry the workspace-scoped application reader and its trace date in the snapshot. A pinned reference reads only its pinned shards; a missing pinned shard refuses the export, without a current-store fallback (REL-375). CSV rows and provenance both carry the release review status. The methods dialog resolves R6 to the same unavailable-data entry as the methods page, keeping its exact documentation key aligned with that status.
Patent browser setup explicitly selects the System appearance and asserts the resolved theme in the search walk; OS dark preference alone does not override the suite’s default Light setting (REL-376).