Licence codes
Every fetched document, every chunk and every Evidence source carries one of eight licence codes
(LICENCE_CODES in api/app/db/models/documents.py). The code is stored per chunk where a field differs
from the document (an abstract under publisher copyright inside an open-access record), and rendering
follows the code of the chunk being cited. Codes are described individually in copy; the product never
summarises a set of codes as a single clearance word.
| Code | Label in the web app | Rendering in the console | Rendering on export |
|---|---|---|---|
cc0 | Public domain dedication (CC0) | full span | full span |
cc_by | Attribution licence (CC BY) | full span | full span with attribution |
cc_by_sa | Attribution, share-alike (CC BY-SA) | full span | full span with attribution and a share-alike notice |
cc_by_nd | Attribution, no derivatives (CC BY-ND): quote only, do not paraphrase | verbatim excerpt with attribution; the chunk is marked quote_only and the context assembler labels it “quote only, do not paraphrase” | listed separately as quotations |
cc_by_nc | Attribution, non-commercial (CC BY-NC): link and locator only | locator plus outbound link | locator plus link |
publisher_copyright | Publisher copyright: link and locator only | locator plus outbound link | locator plus link |
customer_internal | Internal to your organisation | excerpt to program members (ELN entries, SOP renditions) | locator and hash only |
unknown | Licence unknown: link and locator only | locator plus outbound link | locator plus link |
A paraphrased claim whose only sources are cc_by_nd chunks is a citation-coverage warning. customer_internal
content is scoped by program membership plus the source system’s own project scoping; document_chunks
carries organization_id and program_id, so every vector or text query filters on the chunk row.
Chip classes and the evidence panel (R4, designed)
Phase 4 keeps the three rendering groups exactly as api/app/services/documents.py defines them today,
SPAN_LICENCES = {cc0, cc_by, cc_by_sa, customer_internal}, QUOTE_ONLY_LICENCES = {cc_by_nd},
LOCATOR_ONLY_LICENCES = {cc_by_nc, publisher_copyright, unknown}, and the switch stays
chunk_body_allowed(licence_code) per code (ADR 0028
is the only path to change it). What changes is what the reader sees beside the passage: a chip whose text
derives from a closed class, documents.licence_statement_class, with the statement itself as display text
that never decides rendering (ADR 0029).
The evidence panel page describes each rendering in the reader’s words.
| Chip class | Chip text | Codes | Carries |
|---|---|---|---|
public_domain | “public domain” or “open access (CC0)” | cc0 | full span, figures, tables, PDF pages |
cc_by | “open access (CC BY)” | cc_by | as above plus an attribution line (title, authors, source, licence link) on every figure card, pin, table and export |
cc_by_sa | “share-alike” | cc_by_sa | as cc_by plus a share-alike line on every derived table and skill output that mixes share-alike rows |
acknowledgement | “reproduced with acknowledgement” | cc_by as mapped for guidance and registry sources with attribution terms that are not Creative Commons | clauses labelled “excerpt; see full document” |
internal | “internal” | customer_internal | notebook entries and SOP text to program members |
third_party_suspected | “Uploaded by your organisation. Your organisation’s licence applies.” | customer_internal with documents.third_party_suspected | inline to program members only; never in exports, shared boards, lens briefs, shared memory or full-text successors |
locator | “metadata and link” | cc_by_nc, publisher_copyright, unknown | title, authors, journal, year, DOI, “Open at publisher”; the abstract only when the abstract chunk’s own code allows a span, or as a quote capped at 400 characters when it allows a quote |
no_derivatives | “open access, no derivatives” | cc_by_nd | the cited quote in context with an attribution line (title, authors, source, licence link) on the quote and on every pin of it; metadata; “Open at publisher”; no figure capture, no thumbnail, no PDF viewer, no export of derived text |
Eight classes; no_derivatives was added on 2026-09-16 (contract 12.3) because without it a no-derivatives pin
or asset read locator, “metadata and link”. The attribution flag is true for cc_by, cc_by_sa and
cc_by_nd (CC BY-ND requires attribution), and the API and web renderers must agree on it. Fact (verified in
api/app/db/models/workbench.py:38 and :54-57): LICENCE_STATEMENT_CLASSES holds the eight classes and
chip_class_for("cc_by_nd") returns no_derivatives | Consequence: this page and docs/lib/content.ts list
eight. Fact (verified in api/app/services/workbench.py:402-408 and api/app/services/documents.py:634-648):
the API’s attribution_line_for keys on rendering_decision(code).attribution_line, the quote-only decision for
cc_by_nd sets attribution_line=True, and the web renderer (web/components/console/evidence-rules.ts:49)
shows one for the quote mode | Consequence: the API and the web agree on the attribution flag for cc_by,
cc_by_sa and cc_by_nd, and this page describes both the contract and the code; the feature as a whole stays
designed until the R4 gate list passes. New document columns: licence_statement,
licence_verified_on, pmc_prefix, third_party_suspected, third_party_ref, integrity_status
(ok | corrected | retracted), integrity_ref; document_chunks gains asset_id and row_index.
New sources onto the unchanged codes
Every source of the phase-4 catalogue (verified against primary documentation on 2026-09-15) maps onto the existing codes; no code is added or renamed.
| Source class | Sources | Code | Chip class |
|---|---|---|---|
| US government works | PubChem (NCBI data), openFDA, DailyMed, FDA guidance, Federal Register, EPA CTX / ToxRefDB / ToxCast, RxNorm | cc0 | public_domain |
| CC BY | UniProt, AlphaFold DB, SureChEMBL, STRING, BindingDB-curated rows, Reactome icons | cc_by | cc_by |
| Share-alike | ChEMBL (CC BY-SA 3.0), GtoPdb (ODbL / CC BY-SA 4.0), BindingDB ChEMBL-derived rows, Open TG-GATEs | cc_by_sa | cc_by_sa |
| CC0 | RCSB PDB, Reactome data, Open Targets (ChEMBL-derived fields cc_by_sa per field) | cc0 | public_domain |
| Attribution terms that are not CC | ICH, EMA, ClinicalTrials.gov | cc_by | acknowledgement |
| Contractual or unknown | EPO OPS, CDISC Library, USP-NF, Ph. Eur., ECHA, CTIS, WHO ICTRP, FDA Data Dashboard prose | unknown | locator |
| Customer systems and uploads | the ELN connector, the QMS/SOP connector, data-platform and work-tracking connectors, uploads | customer_internal | internal, or third_party_suspected |
Excluded on licence or access grounds: DrugBank beyond its CC0 vocabulary, WHO ICTRP, CDISC standard text,
USP-NF, Ph. Eur., ECHA, EU CTIS, EudraGMDP, the modified Allotrope schema. Every budget row and connection
carrying terms_url, verified_on and verified_by, and the weekly provider_probe that hashes each terms
page and flips a connection to terms_changed, are R5 and designed
(recorded 2026-09-16). Fact (verified in api/app/db/models/connection.py:16): CONNECTION_STATUSES is
pending, connected, error, disabled and rate_budgets has no terms columns; the registered provider_probe
job returns 0 | Consequence: terms_changed cannot occur in R4.
The third-party flag on uploads
On ingest of an uploaded or synced PDF the worker extracts a DOI or publisher metadata (a pattern over the first
pages plus a Crossref lookup on the existing knowledge.crossref budget) and sets
documents.third_party_suspected with third_party_ref. A holder of program.documents.manage sets or clears
the flag with a reason (PATCH /programs/{program_id}/documents/{document_id}/third-party-flag, audited
document.third_party_flag); the control expands inline in the document row. “Share to board” refuses such a
document with 422 third_party_content.
Where codes come from
| Source | Metadata | Abstract or full text |
|---|---|---|
| Europe PMC | open | per the record’s license field; abstracts publisher_copyright unless the field is clear |
| Crossref | metadata | abstracts publisher_copyright |
| OpenAlex | cc0 | reconstructed abstracts publisher_copyright unless the location’s licence is clear, then that code |
| PubMed and PMC | abstracts as excerpt plus link | PMC full text from the public open-data bucket, filtered by the article’s license_code |
| ClinicalTrials.gov, openFDA, Open Targets | public or open | as published |
| ChEMBL | cc_by_sa | share-alike notice on export |
| ELN entries, SOP renditions | customer_internal | customer_internal |
Attribution blocks for exports and reports live in shared/knowledge-attributions.json, one per source key
(europe_pmc, crossref, openalex, pubmed, clinicaltrials_gov, openfda, open_targets,
chembl), rendered verbatim when at least one cited source comes from that provider; legal review of that
file is a gate before R2. The openfda block carries the adverse-event disclaimer that the existence of a
report is not proof that the drug caused the event.
Retention of documents
Documents are a read-side cache written as actor_kind = system (document.ingest). On source deletion,
connection disconnect or tenant offboarding, customer_internal documents move to archived; the worker job
purge_documents removes chunks, embeddings and stored objects after programs.settings.document_hold_days
(default 30) and keeps the locator and hash (document.purge). Documents are fetched by identifier only
(DocumentIngest {identifier_scheme, identifier_value}), through one of the eight sources, under 25 MB and
with a content-type restriction; there is no URL field.
Source: api/app/db/models/documents.py, api/app/db/models/evidence.py, api/app/services/documents.py (SPAN_LICENCES, QUOTE_ONLY_LICENCES, LOCATOR_ONLY_LICENCES, chunk_body_allowed), web/lib/content.ts (licenceLabels), web/lib/api/types.ts, docs/lib/content.ts (LICENCE_STATEMENT_CLASSES, chipTexts), shared/knowledge-attributions.json, shared/tool-catalogue-2026-09-15.md, PRODUCT-CONTRACT.md sections 10.4, 10.10, 12.3 and 12.4, PRODUCT-PLAN.md Part 4 sections 3.5, 5.4 and 6.3 and Part 9 section 3.4, decisions/0028-abstract-excerpt-and-manuscript-display.md, decisions/0029-licence-mapping-attribution-and-third-party-flag.md