feat(military): USPTO PatentsView defense/dual-use patent filing seeder (#2047) (#2091)

* feat(military): USPTO PatentsView defense/dual-use patent seeder (#2047)

* fix(military): correct PatentsView API field names, sort param, and total semantics

- Use nested dot-notation field names required by PatentsView v1 API:
  assignees.assignee_organization (was flat assignee_organization)
  cpc_at_issue.cpc_subclass_id (was non-existent cpc_subgroup_id)
- Split sort into separate s= param; fix per_page -> size in o= param
  (sort inside o= and per_page are both rejected by PatentsView v1)
- Fix listDefensePatents total to reflect full seeded dataset size,
  not the post-filter count (proto doc: "Total number of filings in
  the seeded dataset")

* feat(defense-patents): add DefensePatentsPanel — R&D Signal frontend

Panel displays weekly USPTO defense/dual-use patent filings from seed.
Five tabs: All | Comms (H04B) | Semiconductors (H01L) | Ammunition (F42B)
| AI (G06N) | Biotech (C12N). Shows assignee, title, CPC tag, date, USPTO link.

Wired into panel-layout.ts and registered as 'defense-patents' in panels.ts.

* fix(defense-patents): TTL 3x interval, recordCount, maxStaleMin 2x, wire into App.ts

- CACHE_TTL: 7d → 21d (3× weekly interval) so key survives missed runs
- recordCount: add (d) => d?.patents?.length ?? 0 so seed logs correct count
- health.js maxStaleMin: 10080 → 20160 (2× 7-day interval per gold standard)
- App.ts: import DefensePatentsPanel, add primeTask (initial load) and
  scheduleRefresh at 24h interval (daily poll for weekly data)
This commit is contained in:
Elie Habib
2026-03-26 17:50:37 +04:00
committed by GitHub
parent 1a2f1abf27
commit d4917cf00b
17 changed files with 593 additions and 1 deletions

View File

@@ -345,6 +345,52 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/Error'
/api/military/v1/list-defense-patents:
get:
tags:
- MilitaryService
summary: ListDefensePatents
description: ListDefensePatents retrieves recent defense/dual-use patent filings from USPTO PatentsView.
operationId: ListDefensePatents
parameters:
- name: cpc_code
in: query
description: CPC category filter (e.g. "H04B", "F42B"). Empty returns all categories.
required: false
schema:
type: string
- name: assignee
in: query
description: Assignee keyword filter (case-insensitive substring match). Empty returns all.
required: false
schema:
type: string
- name: limit
in: query
description: Maximum results to return (default 20, max 100).
required: false
schema:
type: integer
format: int32
responses:
"200":
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/ListDefensePatentsResponse'
"400":
description: Validation error
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
default:
description: Error response
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
schemas:
Error:
@@ -1194,3 +1240,60 @@ components:
type: string
description: Airline name (e.g. "Emirates"). Empty if no mapping.
description: WingbitsLiveFlight contains real-time flight position data from the Wingbits ECS network.
ListDefensePatentsRequest:
type: object
properties:
cpcCode:
type: string
description: CPC category filter (e.g. "H04B", "F42B"). Empty returns all categories.
assignee:
type: string
description: Assignee keyword filter (case-insensitive substring match). Empty returns all.
limit:
type: integer
format: int32
description: Maximum results to return (default 20, max 100).
description: ListDefensePatentsRequest filters defense/dual-use patent filings.
ListDefensePatentsResponse:
type: object
properties:
patents:
type: array
items:
$ref: '#/components/schemas/DefensePatentFiling'
total:
type: integer
format: int32
description: Total number of filings in the seeded dataset.
fetchedAt:
type: string
description: ISO 8601 timestamp when data was seeded.
description: ListDefensePatentsResponse contains recent defense/dual-use patent filings.
DefensePatentFiling:
type: object
properties:
patentId:
type: string
description: USPTO patent ID.
title:
type: string
description: Patent title.
date:
type: string
description: Filing date (YYYY-MM-DD).
assignee:
type: string
description: Primary assignee organization name.
cpcCode:
type: string
description: CPC classification code (e.g. "H04B", "F42B").
cpcDesc:
type: string
description: CPC class description.
abstract:
type: string
description: Patent abstract (truncated to 500 chars).
url:
type: string
description: USPTO patent URL.
description: DefensePatentFiling is a single patent filing from a defense/dual-use organization.