From bbc098fba63a94e4e7650a6d07dc19491ca69457 Mon Sep 17 00:00:00 2001 From: Ali Bahaloo Date: Sat, 25 Jul 2026 00:30:29 -0700 Subject: [PATCH 1/5] docs(006): BRD-003 and spec for inventory-driven check via Cisco PSIRT API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Planning artifacts only — no runtime code changes. Adds `brds/003-api-inventory-check.md` (BRD-003) defining a `caia --api` mode that inverts the current question: instead of "given this advisory, which firewalls are affected?", it asks "given my inventory, which firewalls does Cisco list as vulnerable, and to what?". Verdicts come from Cisco's published per-platform/per-release data, so the mode needs no advisory URL and makes no AI call. Output is a self-contained, timestamped HTML report per run. Grounded in a feasibility spike against the real inventory: 70 rows collapse to 27 distinct checks, and 15 rows proved unanswerable (releases Cisco has purged as end-of-support, and model/release pairings Cisco never shipped). That drove the three-verdict model — Impacted / Not impacted / Needs review — where "Not impacted" requires Cisco to positively confirm both the release and the platform, so a data-quality problem can never be read as a clean bill of health. Adds `specs/006-api-inventory-check/` with the derived spec (5 prioritized user stories, 57 functional requirements, 20 success criteria) and its quality checklist, and points `.specify/feature.json` at the new feature directory. Two governance items deliberately deferred to /speckit-plan: - the mode contacts Cisco auth/advisory hosts the analyzer does not contact today, which Technology & Data Constraints make a reviewed change requiring a constitution amendment; - this mode labels an undecidable device "Needs review" while Principle IV and the existing report say "Indeterminate" — align the vocabulary or record the divergence. Co-Authored-By: Claude Opus 5 --- .specify/feature.json | 2 +- brds/003-api-inventory-check.md | 342 ++++++++++++++++++ .../checklists/requirements.md | 54 +++ specs/006-api-inventory-check/spec.md | 271 ++++++++++++++ 4 files changed, 668 insertions(+), 1 deletion(-) create mode 100644 brds/003-api-inventory-check.md create mode 100644 specs/006-api-inventory-check/checklists/requirements.md create mode 100644 specs/006-api-inventory-check/spec.md diff --git a/.specify/feature.json b/.specify/feature.json index d0debff..f7e88b1 100644 --- a/.specify/feature.json +++ b/.specify/feature.json @@ -1,3 +1,3 @@ { - "feature_directory": "specs/005-self-uninstall" + "feature_directory": "specs/006-api-inventory-check" } diff --git a/brds/003-api-inventory-check.md b/brds/003-api-inventory-check.md new file mode 100644 index 0000000..f44c00f --- /dev/null +++ b/brds/003-api-inventory-check.md @@ -0,0 +1,342 @@ +# Business Requirements Document (BRD): Inventory-Driven Vulnerability Check via the Cisco PSIRT API + +## Document Control + +| Field | Value | +| ----------------- | ------------------------------------------------------------ | +| BRD ID | BRD-003 | +| Title | Inventory-Driven Vulnerability Check via the Cisco PSIRT API (`caia --api`) | +| Author | Ali Bahaloo / TELUS Digital | +| Status | Draft | +| Version | 0.1.0 | +| Created | 2026-07-25 | +| Last updated | 2026-07-25 | +| Related documents | Repo: https://github.com/xavient/cisco-advisory-impact-agent · BRD-001 (Self-Update Mechanism): `brds/001-auto-updater.md` · BRD-002 (Self-Uninstall Command): `brds/002-uninstall.md` · Constitution: `.specify/memory/constitution.md` · Cisco PSIRT openVuln API: https://developer.cisco.com/docs/psirt/ · Cisco Software Checker: https://sec.cloudapps.cisco.com/security/center/softwarechecker.x | + +## 1. Executive Summary + +Today the tool answers one question: *given this Cisco advisory, which of my firewalls are affected?* It requires an analyst to already have an advisory or Event Response link in hand, and it reaches that answer by having an AI read the advisory's prose and compare it against the inventory. This BRD defines a second, complementary mode — `caia --api` — that answers the inverse and more operationally useful question: *given my whole inventory, which firewalls are vulnerable right now, and to what?* It asks Cisco's own PSIRT API directly, per device, using the same data the public Cisco Software Checker uses, and produces a self-contained, timestamped HTML report listing every device with a verdict of **Impacted**, **Not impacted**, or **Needs review**, plus the advisories that justify each Impacted verdict. Because Cisco supplies the answer, this mode needs no AI judgement and no advisory URL. + +## 2. Business Context & Problem Statement + +The existing flow is advisory-driven and reactive. It only runs when someone notices an advisory or Event Response worth checking, and it is limited to the advisories that ERP references. Nobody can currently ask "what is my exposure across the fleet today?" without checking every device by hand in Cisco's web Software Checker — a per-device, point-and-click exercise across a ~1,000-row inventory. + +Consequences today: + +- **No fleet-wide view.** Exposure is only ever assessed one advisory at a time. There is no run that says "here is every vulnerable firewall we own." Gaps persist simply because no advisory prompted a check. +- **Manual checking does not scale.** The web Software Checker requires selecting a product, a hardware platform, and a release for each device. At inventory scale this is not done, so it is not done at all. +- **The verdict depends on AI interpretation.** The current mode has an AI read "Vulnerable Products" prose and infer version overlap. Cisco publishes the authoritative per-platform, per-release answer directly, including the release that fixes each issue. Deriving it by inference where an authoritative source exists adds avoidable uncertainty to a security decision. +- **No remediation target.** The current report says which firewalls are affected but not what to upgrade to. Cisco's API returns the first fixed release for every finding. +- **Inventory data quality is invisible.** A feasibility spike against the real inventory found that **15 of 70 rows could not be answered at all** — versions Cisco has purged as end-of-support, and model/release combinations Cisco never shipped (for example ASA 9.18 on ASA 5500-X hardware, and FTD 7.4.0 on an ISA-3000). Those rows look identical to "no advisories found." A check that reports them as safe is worse than no check, and today nothing surfaces them. + +The cost is unmeasured fleet exposure, remediation work that is scheduled from incomplete information, and a standing risk that a data-quality problem in the inventory is silently read as a clean bill of health. + +## 3. Business Objectives & Goals + +- **G1** — Let an analyst assess the entire firewall inventory against Cisco's published vulnerability data in a single command, without needing an advisory link. +- **G2** — Base each verdict on Cisco's authoritative per-platform, per-release answer rather than on inference, so findings are reproducible and defensible. +- **G3** — Never present an unanswerable device as safe: distinguish "Cisco says this is clean" from "we could not determine this," and say why. +- **G4** — Give each finding an actionable remediation target — the release that fixes it — and a direct route to the published advisory. +- **G5** — Produce a report that can be read, shared, and acted on without a spreadsheet tool, and that preserves a durable per-run record. +- **G6** — Be transparent about what the check does and does not cover, so its output is never over-trusted. +- **G7** — Add this mode without changing the behaviour of the existing advisory-driven analysis. + +## 4. Stakeholders & Users + +| Stakeholder / user | Role in this product | What they need from it | +| ------------------ | -------------------- | ---------------------- | +| Security / network analyst | Primary user | A fleet-wide answer in one command; per-device advisories with the release that fixes them; confidence that "Not impacted" means Cisco said so | +| Firewall / patching engineer | Downstream actor | A worklist they can prioritise — which devices, which advisories, which target release — reachable without hunting through Cisco's site | +| Team lead / security manager | Reviewer, reporting | A shareable per-run snapshot of fleet exposure and its trend; visibility into how much of the inventory could not be assessed | +| Inventory owner | Indirect | Notification that specific inventory rows carry models or releases Cisco does not recognise, so the source data can be corrected | +| IT / security review | Reviewer | Assurance that Cisco credentials are handled like existing secrets, and that externally-supplied advisory content cannot compromise the generated report | +| Support / help desk | Indirect | A self-explanatory report that reduces "what does this mean?" questions | + +## 5. Scope + +### 5.1 In Scope + +- A command-line option, `caia --api`, that checks the firewall inventory against Cisco's published advisory data per device, instead of analysing a supplied advisory or Event Response link. +- Assigning every inventory row exactly one verdict: **Impacted**, **Not impacted**, or **Needs review**. +- Reconciling the inventory's software-release strings with Cisco's canonical release format, so releases recorded in operational shorthand are still matched. +- Determining each device's Cisco hardware platform from its inventory model, using the set of platforms Cisco publishes at run time. +- Detecting and reporting, as **Needs review** with a stated reason, every case where a trustworthy verdict cannot be reached — an unrecognised release, a release Cisco never shipped on that model, a model that cannot be identified, or an incomplete response from Cisco. +- Producing one self-contained, timestamped HTML report per run in the tool's output folder, listing every analysed device with its original inventory columns, its verdict, and the advisories behind an Impacted verdict. +- Presenting, for each advisory, its identifier, title, severity, a link to the published advisory, and the release that first fixes it. +- Letting a reader of the report filter and sort by verdict and by the inventory's priority column, and expand or collapse the advisory detail for a device. +- Stating in the report what the check covered — run time, inventory file, per-verdict counts — and the known limits of Cisco's data. +- Extending the tool's existing `caia --config` flow to prompt for and store the Cisco API credentials per user, so they are captured interactively once and found by every later run from any folder — the same path by which the AI service key is already captured. +- Checking the Cisco credentials against Cisco during `caia --config` and telling the user whether they are valid, so a wrong or truncated credential is caught at setup rather than on a later run. +- Operating within Cisco's published request quotas for a full ~1,000-row inventory. + +### 5.2 Out of Scope + +- **Changing the existing advisory-driven mode.** Running the tool without `--api` behaves exactly as it does today, including its Excel report. The two modes answer different questions and coexist. +- **Any AI involvement in this mode.** Verdicts come from Cisco's response alone. The AI service is not called and its credential is not required for an `--api` run. +- **Excel output, or any machine-readable export, for this mode.** v1 produces HTML only. Run-to-run comparison, dashboard ingestion, and adding tracking columns are deliberately deferred — see Open Questions. +- **Judging whether a vulnerable feature is actually enabled.** Cisco's data does not account for enabled or disabled configuration, so an Impacted verdict means "this release on this platform is listed as affected," not "this device is exploitable." The tool discloses this rather than resolving it. +- **Assessing non-firewall or non-Cisco inventory.** Only the Cisco product families Cisco's own checker supports are in scope; anything else becomes **Needs review**. +- **Verifying the AI service key.** Credential verification during setup is added for the Cisco credentials only. Whether the existing AI service key should be checked the same way is a separate decision, deliberately not bundled here. +- **Correcting the inventory.** The tool surfaces rows Cisco cannot recognise; editing the source inventory remains the inventory owner's responsibility. +- **Retrieving advisories Cisco excludes from this data set** — notably advisories published before Cisco's per-family cut-off dates. The tool discloses the limit; it does not work around it. +- **Automated or scheduled runs, alerting, or ticket creation.** The analyst runs the command. +- **Opening or hosting the report.** The tool writes a file to disk; viewing and distributing it is the user's action. + +## 6. User Journeys *(feeds the spec's prioritized user stories)* + +### Journey 1 — Assess the whole inventory in one command (Priority: P1) + +- **Actor:** Security / network analyst with the inventory in their working folder and Cisco API credentials configured. +- **Trigger:** They run `caia --api`. +- **Outcome / value:** A single HTML report naming every firewall they own and whether Cisco considers it vulnerable — without needing an advisory link or an AI call. +- **Flow:** + 1. The analyst runs `caia --api` in the folder holding their inventory. + 2. The tool locates and loads the inventory, reporting how many devices it will assess. + 3. For each distinct combination of product family, hardware platform, and software release in the inventory, it asks Cisco which advisories apply. + 4. It assigns every device a verdict of Impacted, Not impacted, or Needs review. + 5. It writes a timestamped HTML report to the output folder and prints its location. +- **Acceptance:** + - **Given** a valid inventory and configured credentials, **When** the analyst runs `caia --api`, **Then** a new timestamped HTML report is created in the output folder and its path is reported. + - **Given** the run completes, **When** the report is opened, **Then** every row of the source inventory appears exactly once, retaining its original columns, with exactly one verdict. + - **Given** Cisco returns one or more advisories for a device's platform and release, **When** the verdict is assigned, **Then** that device is Impacted and those advisories are listed against it. + - **Given** a report already exists for the same timestamp, **When** a new report is written, **Then** the existing report is never overwritten. + - **Given** the analyst runs the tool without `--api`, **When** it executes, **Then** the existing advisory-driven behaviour and its Excel report are unchanged. + +### Journey 2 — Never be told a device is safe when it could not be checked (Priority: P1) + +- **Actor:** Security / network analyst reading the report to decide what needs no action. +- **Trigger:** The inventory contains a release or model Cisco does not recognise, or Cisco cannot be reached for a device. +- **Outcome / value:** Unanswerable devices are called out as **Needs review** with the reason, so a data-quality problem is never mistaken for a clean device — and the reason tells the inventory owner what to fix. +- **Flow:** + 1. The tool asks Cisco about a device's platform and release. + 2. Cisco reports no applicable advisories, or rejects the release, or the request fails. + 3. The tool establishes whether Cisco recognises the release at all, and whether Cisco lists that release as shipping on that device's platform. + 4. Only when both are confirmed and no advisories are returned does it record Not impacted; otherwise it records Needs review with a plain-language reason. +- **Acceptance:** + - **Given** a device whose release Cisco does not recognise, **When** the verdict is assigned, **Then** it is Needs review and the report states that Cisco does not recognise that release. + - **Given** a device whose release Cisco recognises but does not list for that device's platform, **When** the verdict is assigned, **Then** it is Needs review and the report states which platforms Cisco does list for that release. + - **Given** a device whose model cannot be identified as a Cisco platform, **When** the verdict is assigned, **Then** it is Needs review and the report states that the model could not be identified. + - **Given** a request to Cisco fails or returns an incomplete answer for a device, **When** the verdict is assigned, **Then** it is Needs review and never Not impacted. + - **Given** Cisco confirms both the release and the platform and returns no advisories, **When** the verdict is assigned, **Then** and only then is it Not impacted. + - **Given** a release recorded in operational shorthand such as `9.16(4)67`, **When** it is checked, **Then** it is matched against Cisco's equivalent canonical release rather than reported as unrecognised. + +### Journey 3 — Act on the findings from the report (Priority: P2) + +- **Actor:** Firewall / patching engineer planning remediation. +- **Trigger:** They open the HTML report produced by a run. +- **Outcome / value:** They can narrow the report to what matters, see what each finding requires, and reach the published advisory in one click — without a spreadsheet tool or a Cisco site search. +- **Flow:** + 1. The engineer opens the report file. + 2. They filter to Impacted devices and sort by the inventory's priority column. + 3. For a device, they expand its advisories and read each one's severity and the release that fixes it. + 4. They follow an advisory link to Cisco's published advisory for detail. +- **Acceptance:** + - **Given** the report is open, **When** the engineer filters by verdict, **Then** only devices with that verdict remain visible. + - **Given** the report is open, **When** the engineer sorts by the inventory's priority column, **Then** rows reorder accordingly. + - **Given** a device with many advisories, **When** its detail is collapsed, **Then** the row stays readable, and expanding it reveals the full list. + - **Given** an advisory is listed, **When** the engineer reads it, **Then** its identifier, title, severity, and the release that first fixes it are shown, and its identifier links to Cisco's published advisory. + - **Given** the report file is opened on a machine with no network access or is viewed after being emailed, **When** it renders, **Then** its layout, filtering, and sorting still work. + +### Journey 4 — Set up Cisco API access once, through `caia --config` (Priority: P2) + +- **Actor:** Analyst running the API mode for the first time, or a team lead onboarding the team. +- **Trigger:** They run `caia --config`, or they run `caia --api` before any Cisco credentials have been saved. +- **Outcome / value:** The same one-command setup flow that already captures the AI service key also captures the two Cisco API credentials. The analyst pastes them into the terminal once and every later run, from any folder, finds them — no file to create, no environment to manage. +- **Flow:** + 1. The analyst runs `caia --config`. + 2. The flow prompts, in one linear pass, for every credential and setting the tool uses — including the Cisco client identifier and the Cisco client secret — so each can be pasted straight into the terminal. Any prompt can be skipped by the user who does not need it. + 3. The client identifier is prompted visibly; the client secret is not shown in readable form, and once entered the flow confirms that a value was captured and how long it was, so a failed or truncated paste is immediately obvious. + 4. Where a value is already saved, the prompt says so and pressing Enter keeps it. + 5. With both Cisco values in hand, the flow checks them against Cisco and reports whether they are valid before finishing. + 6. The values are saved to the same per-user configuration the tool already uses, protected the same way, and found by later runs from any folder. + 7. Should the analyst instead run `caia --api` with no Cisco credentials saved, the tool refuses to run, names what is missing, and points them at `caia --config`. +- **Acceptance:** + - **Given** the analyst runs `caia --config`, **When** the flow runs, **Then** it prompts for both the Cisco client identifier and the Cisco client secret in addition to the settings it already collects, and saves them to the per-user configuration. + - **Given** the analyst is prompted for the Cisco client identifier, **When** they paste it, **Then** it is shown as they enter it; **and Given** they are prompted for the client secret, **When** they paste it, **Then** it is not shown in readable form. + - **Given** a secret has been entered, **When** the prompt completes, **Then** the flow confirms that a value was captured and its length, without revealing the value itself. + - **Given** a Cisco credential is already saved, **When** the analyst is prompted for it, **Then** the flow indicates a value exists and pressing Enter leaves it unchanged. + - **Given** both Cisco values have been supplied, **When** the flow checks them and Cisco accepts them, **Then** it states plainly that the credentials are valid. + - **Given** both Cisco values have been supplied, **When** Cisco rejects them, **Then** the flow reports the reason Cisco gave, offers to re-enter them, and does not silently save the rejected values. + - **Given** both Cisco values have been supplied, **When** Cisco cannot be reached at all, **Then** the flow says so distinctly from a rejection and lets the analyst save the credentials unverified with a clear warning. + - **Given** the analyst skipped the Cisco prompts, **When** the flow completes, **Then** no verification request is made to Cisco. + - **Given** verification succeeds, fails, or cannot run, **When** any message is shown, **Then** it contains no part of either credential value. + - **Given** Cisco credentials were saved by `caia --config`, **When** the analyst runs `caia --api` from any other folder, **Then** the run proceeds without re-entering them. + - **Given** the analyst only ever uses the advisory-driven mode, **When** they run `caia --config`, **Then** they can complete the flow without supplying Cisco credentials, and the existing mode still runs. + - **Given** the analyst only ever uses `--api`, **When** they run it, **Then** it does not require the AI service key to be configured. + - **Given** no Cisco credentials are saved, **When** the analyst runs `caia --api`, **Then** the tool refuses to run, names what is missing, directs them to `caia --config`, and makes no requests to Cisco. + - **Given** the saved credentials are rejected by Cisco, **When** a run starts, **Then** the tool reports an authentication problem distinctly from "no advisories apply" and does not emit a report of Not impacted devices. + - **Given** any run or configuration session, **When** it completes or fails, **Then** no credential value appears in the report, in printed output, or in a filename. + +### Journey 5 — Understand what the check did and did not cover (Priority: P3) + +- **Actor:** Team lead or reviewer receiving the report second-hand. +- **Trigger:** They read a report they did not run. +- **Outcome / value:** They can see when it ran, against what, how much of the inventory was answerable, and the known limits of the underlying data — so they do not over-trust it. +- **Flow:** + 1. The reviewer opens the report. + 2. A summary states when the run happened, which inventory file it used, how many devices were assessed, and the count per verdict. + 3. The same summary states the known coverage limits of Cisco's data. +- **Acceptance:** + - **Given** any report, **When** it is opened, **Then** it shows the run date and time, the inventory file used, the number of devices assessed, and a count per verdict. + - **Given** any report, **When** it is read, **Then** it states that Cisco's data excludes advisories published before Cisco's per-family cut-off dates, and that a verdict does not account for whether a vulnerable feature is enabled. + - **Given** a report contains Needs review devices, **When** it is read, **Then** their number is visible in the summary and not only discoverable row by row. + +## 7. Business Requirements + +| ID | Requirement | Priority | +| ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------- | +| BR-01 | The product MUST provide a `--api` option that assesses the loaded inventory against Cisco's published advisory data per device, requiring no advisory or Event Response URL. | P1 | +| BR-02 | The product MUST leave the existing advisory-driven mode, including its Excel report, unchanged when `--api` is not supplied. | P1 | +| BR-03 | The product MUST assign every row of the inventory exactly one verdict from: Impacted, Not impacted, Needs review. | P1 | +| BR-04 | The product MUST classify a device Impacted only when Cisco returns at least one advisory applying to that device's software release on that device's hardware platform. | P1 | +| BR-05 | The product MUST classify a device Not impacted only when Cisco recognises both the release and the platform and returns no applicable advisories. | P1 | +| BR-06 | The product MUST classify a device Needs review, with a human-readable reason, whenever a trustworthy verdict cannot be established — including an unrecognised release, a release Cisco does not list for that platform, an unidentifiable model, or a failed or incomplete response. | P1 | +| BR-07 | The product MUST NOT report a device as Not impacted when Cisco does not recognise its release or does not list that release for its platform. | P1 | +| BR-08 | The product MUST reconcile inventory release strings recorded in operational shorthand with Cisco's canonical release identifiers, including releases annotated with a companion product or build suffix. | P1 | +| BR-09 | The product MUST determine each device's Cisco hardware platform from its inventory model, and MUST obtain the valid set of platforms from Cisco at run time rather than relying on a fixed built-in list. | P1 | +| BR-10 | The product MUST produce exactly one self-contained HTML report per run, written to the tool's output folder with a timestamped name, and MUST never overwrite an existing report. | P1 | +| BR-11 | The report MUST list every analysed device once, retaining the inventory's original columns, alongside its verdict and — for an Impacted verdict — the advisories that justify it. | P1 | +| BR-12 | The product MUST treat all advisory content received from Cisco as untrusted text, and MUST NOT allow that content to alter the structure, styling, or behaviour of the generated report. | P1 | +| BR-13 | The product MUST refuse to run, with a message naming what is missing and directing the user to `caia --config`, when Cisco API credentials have not been configured, and MUST make no requests to Cisco in that case. | P1 | +| BR-14 | The product MUST NOT expose credential values in the report, in printed output, or in any filename it creates. | P1 | +| BR-15 | The product MUST operate within Cisco's published request quotas, and MUST NOT issue a duplicate check for devices that share the same product family, platform, and release. | P1 | +| BR-16 | The product MUST distinguish an authentication or connectivity failure from a "no advisories apply" answer, and MUST NOT emit Not impacted verdicts derived from a failed run. | P1 | +| BR-17 | For each listed advisory the report MUST show its identifier, title, severity, and a working link to Cisco's published advisory, and SHOULD show its CVE identifiers and the release that first fixes it. | P2 | +| BR-18 | The report MUST let a reader filter and sort by verdict and by the inventory's priority column, and expand or collapse a device's advisory detail, without any external tool or network access. | P2 | +| BR-19 | `caia --config` MUST prompt for the Cisco client identifier and the Cisco client secret, alongside the settings it already collects, so a user can paste both into the terminal in one guided session. | P1 | +| BR-20 | `caia --config` MUST save the Cisco credentials to the same per-user configuration the tool already uses, protected the same way, so later runs from any folder find them without re-entry. | P1 | +| BR-21 | `caia --config` MUST indicate when a Cisco credential is already saved and MUST leave it unchanged when the user submits an empty response, matching how it treats the existing AI service key. | P2 | +| BR-22 | The product MUST let a user complete `caia --config` while supplying only the credentials for the mode they use, and each mode MUST require only its own credentials — `--api` MUST NOT require the AI service key, and the advisory-driven mode MUST NOT require Cisco credentials. | P1 | +| BR-23 | `caia --config` MUST prompt for the Cisco client identifier visibly, since it is an identifier rather than a secret, and MUST NOT echo the Cisco client secret in readable form. | P2 | +| BR-24 | `caia --config` MUST confirm, immediately after a secret is entered, that a value was captured and how many characters it contained, so a truncated or failed paste is obvious without revealing the value. It SHOULD additionally give visible feedback while the secret is being entered (for example a masking character per keystroke) where the terminal supports it, falling back to a non-echoing prompt where it does not. | P2 | +| BR-25 | `caia --config` MUST verify the Cisco credentials with Cisco before completing, and MUST state plainly whether they are valid. | P1 | +| BR-26 | When Cisco rejects the credentials, `caia --config` MUST show the reason Cisco gave, MUST offer to re-enter them, and MUST NOT silently save values that were rejected. | P1 | +| BR-27 | When Cisco cannot be reached to verify, `caia --config` MUST distinguish that from a rejection and MUST allow the user to save the credentials unverified with a clear warning, so a network or proxy outage never prevents configuration. | P1 | +| BR-28 | Verification MUST NOT display, log, or write any part of a credential value in its success, failure, or warning messages. | P1 | +| BR-29 | `caia --config` MUST attempt verification only when both Cisco values are available for the session, and MUST make no request to Cisco when the user skipped those prompts. | P2 | +| BR-30 | The product MUST continue to honour Cisco credentials supplied through the environment, taking precedence over saved values, so automated use remains possible; `caia --config` remains the documented and expected path for a person. | P2 | +| BR-31 | The product MUST report progress while running so a full-inventory run does not appear stalled, and MUST complete an inventory of approximately 1,000 devices within Cisco's quotas. | P2 | +| BR-32 | The product MUST signal the outcome of the run through its process exit status so automation can distinguish a completed run from a failure. | P2 | +| BR-33 | The report MUST state the run date and time, the inventory file used, the number of devices assessed, and a count per verdict. | P3 | +| BR-34 | The report MUST state the known coverage limits of Cisco's data — the per-family advisory publication cut-offs, and that a verdict does not account for whether a vulnerable feature is enabled. | P3 | +| BR-35 | The product's documentation MUST explain that `--api` produces an HTML report while the default mode produces an Excel report, and why the two modes answer different questions. | P3 | +| BR-36 | The product's documentation MUST list the Cisco API credentials among the prerequisites a new user obtains before first use, and MUST show `caia --config` as the way to supply them. | P3 | + +## 8. Success Metrics & Measurable Outcomes + +- **SC-01** — An analyst can assess the entire firewall inventory with a single command and no advisory link, producing one report. +- **SC-02** — 100% of inventory rows appear in the report with exactly one verdict; no row is silently dropped. +- **SC-03** — 0% of devices whose release or platform Cisco does not recognise are reported as Not impacted; every such device is Needs review with a stated reason. +- **SC-04** — 100% of Needs review devices carry a reason a reader can act on without consulting the tool's authors. +- **SC-05** — 100% of Impacted devices list at least one advisory, and every listed advisory carries a working link to Cisco's published advisory. +- **SC-06** — Every listed advisory that Cisco supplies a fixed release for shows that release, giving the engineer a remediation target without a further lookup. +- **SC-07** — A run against an inventory of approximately 1,000 devices completes without exceeding Cisco's request quotas and without a partial or missing report. +- **SC-08** — Repeated runs never overwrite an earlier report; each run leaves a distinct, durable file. +- **SC-09** — The report renders, filters, and sorts correctly when opened with no network access and after being copied or emailed to another machine. +- **SC-10** — No credential value appears in any report, printed output, or filename across any run, successful or failed. +- **SC-11** — A run started without Cisco credentials, or with credentials Cisco rejects, produces a clear diagnostic and no report of Not impacted devices. +- **SC-12** — A new user can go from having their Cisco credentials in hand to a completed `--api` run using only `caia --config` and `caia --api`, without creating a file or setting an environment variable. +- **SC-13** — A user of only one mode can configure and run that mode without supplying the other mode's credentials. +- **SC-14** — A wrong, truncated, or expired Cisco credential is detected during `caia --config` rather than on a later run, and the user is told why. +- **SC-15** — Configuration remains completable when Cisco cannot be reached, with the unverified state disclosed rather than the setup being blocked. +- **SC-16** — After entering the client secret, the user can tell from the confirmation alone whether their paste landed intact, without the value being displayed. +- **SC-17** — Every report states its coverage limits, so a reader who did not run it can judge how far to trust it. +- **SC-18** — Running the tool without `--api` produces the same result it did before this feature existed. + +## 9. Assumptions + +- Cisco API credentials (a client identifier and secret) are obtainable by each user from Cisco's developer portal, and are the user's own to manage — mirroring how each user obtains their own AI service key today. +- Because the tool is installed as a `uv` tool and run from arbitrary working folders, `caia --config` is in practice the only credential path a user exercises. A working-folder `.env` file is a convenience for automation that a normal install never relies on, so this feature must not require one; environment variables remain supported but are not the expected route. +- Both Cisco credential values are short enough to paste into a terminal prompt in one action, and users will paste rather than type them. +- The inventory keeps its current shape: one row per firewall, with a name, a model, a product-family/type, a software release, and a priority. Column-header variations continue to be tolerated as they are today. +- The product families present in the inventory today — ASA, FTD and FMC — are the families this mode must handle first; other Cisco families Cisco's checker supports are a natural extension, and anything unsupported becomes Needs review. +- Cisco's published data is the authority for whether a release on a platform is affected; the tool reports it rather than second-guessing it. +- Cisco publishes, and the tool can retrieve at run time, both the set of valid hardware platforms per product family and the set of valid releases — so neither needs to be hardcoded and both can change without a tool release. +- Devices sharing the same family, platform and release have the same verdict, so one check can serve many devices; a real inventory collapses to far fewer checks than it has rows. +- An `--api` run makes no AI call, so it does not require the AI service credential and incurs no AI cost. +- The report is a file the user opens themselves; the tool does not need to launch a browser. +- One report per run is the desired behaviour; reports accumulate in the output folder as they do today. + +## 10. Constraints + +- The tool's minimal-dependency posture applies: this mode must not introduce dependencies beyond what the capability genuinely requires, and any addition is a reviewed decision. +- Behaviour and output must be identical across Windows, macOS, and Linux. +- Cisco's published request quotas are a hard ceiling; the design must stay within them for a full-inventory run rather than relying on the user to throttle. +- The run requires network access to Cisco's authentication and advisory endpoints. These are additional external hosts beyond those the tool contacts today, and must be recorded as permitted destinations. +- Credential handling must match the tool's existing posture: stored per user outside the installed code, never transmitted anywhere but the issuing service, never written to reports or logs. +- Advisory content arrives as externally-authored markup and must never be able to influence the generated report's structure or behaviour. +- Reports must never be overwritten; an earlier run's record must remain intact. +- The report must be a single file that works offline, so it survives being emailed, archived, or opened behind a restrictive corporate network. + +## 11. Dependencies + +- **Input** — Cisco's PSIRT advisory service, which supplies the per-platform, per-release advisory answer, the fixed-release information, and the catalogues of valid platforms and releases. The entire verdict rests on it. +- **Input** — Cisco's authentication service, which issues the short-lived access token each run needs. +- **Input** — The user's firewall inventory file in the working folder, discovered and loaded exactly as the existing mode does. +- **Input** — The user's Cisco API credentials, captured by `caia --config` into the per-user configuration (or, for automation only, supplied through the environment). +- **Output** — The tool's output folder, where the timestamped HTML report is written. +- **Related** — The existing inventory-loading component, whose behaviour (file discovery, column tolerance, grouping of identical devices) this mode reuses rather than duplicates. +- **Related** — The existing per-user configuration component and its `caia --config` flow, extended to prompt for and hold the Cisco credentials alongside the AI service key. This is the single place credentials are captured and the only one a normal install uses. +- **Related** — BRD-001 and BRD-002, whose conventions for confirmation, clear refusal, actionable errors, and exit status this mode should follow. + +## 12. Risks & Mitigations + +| Risk | Impact | Likelihood | Mitigation | +| ---------------------------------------------------------------------------------------------------------- | ------ | ---------- | ---------- | +| A device that could not be assessed is read as safe, and remediation skips it | H | H | Three-verdict model with a mandatory reason; Not impacted requires positive confirmation of both release and platform (BR-05, BR-06, BR-07) | +| Cisco's data excludes advisories published before its per-family cut-off, so an Impacted list is incomplete and a Not impacted verdict is narrower than it appears | H | H | State the limit prominently in every report; keep the existing advisory-driven mode available for older advisories (BR-27, Section 5.2) | +| An Impacted verdict overstates risk because the vulnerable feature is not enabled on that device | M | H | Disclose that verdicts do not account for configuration; frame Impacted as "listed as affected," not "exploitable" (BR-27) | +| Inventory releases or models Cisco does not recognise produce a large Needs review population that erodes confidence in the report | M | H | Reconcile shorthand releases before deciding (BR-08); give each Needs review row a specific, correctable reason so the inventory can be fixed (BR-06, SC-04) | +| Externally-authored advisory content compromises the generated report when opened in a browser | H | M | Treat all Cisco-supplied content as untrusted text that cannot affect report structure or behaviour (BR-12) | +| A new hardware platform or release appears and a fixed built-in list makes matching devices unassessable | M | M | Retrieve platform and release catalogues from Cisco at run time (BR-09) | +| Request quotas are exceeded on a large inventory, producing a partial or failed run | M | M | Collapse duplicate checks and pace requests within published quotas; verify against a full-size inventory (BR-15, BR-24, SC-07) | +| An authentication or network failure is misread as "nothing applies," producing a falsely clean report | H | M | Distinguish failure from a negative answer and suppress verdicts derived from failed requests (BR-16, SC-11) | +| No machine-readable output means run-to-run comparison must be done by eye | M | M | Accepted for v1 as a deliberate scope decision; recorded in Open Questions so it can be revisited once the mode is in use | +| Two report formats across two modes confuses users about which to run | L | M | Document why the modes differ and what each answers (BR-28) | +| A user configures one mode's credentials and is blocked from the mode they actually wanted, or is forced to supply credentials for a mode they never use | M | M | Make every credential prompt skippable and gate each mode only on its own credentials (BR-21, BR-22, SC-15) | +| A pasted credential is mistyped or truncated and the failure only surfaces mid-run as an authentication error | L | M | Verify the credentials against Cisco during setup and report the reason on rejection (BR-25, BR-26, SC-16); report authentication failure distinctly at run time too (BR-16, SC-11) | +| A secret entered at a hidden prompt shows no feedback, so the user cannot tell a paste succeeded | L | M | Confirm the captured length immediately after entry, and mask keystrokes where the terminal supports it (BR-24, SC-18) | +| A network or proxy outage during setup prevents a user from configuring the tool at all | M | M | Treat unreachable-for-verification as distinct from rejected and allow saving unverified with a warning (BR-27, SC-17) | +| Per-keystroke masking behaves inconsistently across terminals and platforms, or mishandles a paste | M | M | Masking is a SHOULD with a defined fallback to a non-echoing prompt; the length confirmation is the MUST that delivers the actual assurance (BR-24) | +| Cisco changes its data shape or endpoints, breaking the mode | M | L | Treat an unexpected response as Needs review rather than a silent verdict; fail loudly rather than quietly (BR-06, BR-16) | + +## 13. Open Questions + +- Should an Impacted verdict optionally be passed to the AI for the judgement Cisco's data cannot make — whether the vulnerable feature is plausibly enabled — as a hybrid of the two modes? (Leaning: not in v1; keep this mode fully deterministic and AI-free.) +- Should the two modes ever be combinable in one run, or do they remain mutually exclusive? +- Should the tool cache Cisco's platform and release catalogues between runs to conserve quota, and if so how would a user force a refresh? +- Should Needs review be a single verdict, or split into distinct reasons the reader can filter on independently (release unknown to Cisco / release not shipped on this model / model unrecognised / check failed)? +- Should the report group by device, by advisory, or offer both views? The inventory-per-row layout is confirmed; an advisory-centric view may be more useful for planning a single upgrade campaign. +- Should a run where every device ends as Needs review be treated as a failed run, or a successful run with a wholly inconclusive result? +- Which product families beyond ASA, FTD and FMC must be supported before this is considered complete for the team's real inventory? +- Should a future revision add a machine-readable per-run artifact to support run-to-run comparison and downstream ingestion, given v1 is HTML-only? +- Should the existing AI service key also be verified at setup time, for symmetry with the Cisco credentials? (Out of scope here — see Section 5.2 — but a natural follow-up once the verification pattern exists.) + +_Resolved during BRD review:_ the verdict set is **three values** — Impacted / Not impacted / Needs review (BR-03); the output is **HTML only**, one self-contained timestamped file per run, with no Excel or machine-readable export in v1 (Section 5.2, BR-10); the existing advisory-driven mode and its Excel report are **unchanged** (BR-02); this mode makes **no AI call** (Section 5.2); Cisco credentials are captured **interactively through `caia --config`**, which is the expected and documented path — a working-folder `.env` is not relied upon, since a `uv`-tool install run from arbitrary folders never reads one (BR-19, BR-20, Section 9); the client identifier is prompted **visibly** and the client secret is **not echoed**, with a length confirmation after entry and optional keystroke masking (BR-23, BR-24); `caia --config` prompts for **all** credentials in **one linear pass**, each skippable, rather than branching on which mode the user intends to use (BR-19, BR-22); and `caia --config` **verifies the Cisco credentials against Cisco before finishing**, reporting validity plainly, distinguishing a rejection from an unreachable service (BR-25, BR-26, BR-27). + +## 14. Glossary + +| Term | Definition | +| ---- | ---------- | +| `caia` | The command the tool installs on the user's PATH; what users actually type. | +| `--api` | The new option that switches the tool from analysing a supplied advisory to assessing the whole inventory against Cisco's published data. | +| `caia --config` | The tool's existing interactive setup command, which prompts for credentials and settings and saves them per user. Extended by this BRD to also capture the Cisco client identifier and client secret. | +| Per-user configuration | The stored credentials and settings, kept in an OS-appropriate per-user location outside the installed code and outside any working folder, so any run from any folder finds them. | +| Cisco client identifier / client secret | The two values Cisco issues for API access. The identifier names the calling application and is not itself secret; the secret authenticates it and is handled as a secret throughout. | +| Credential verification | The check `caia --config` performs against Cisco after collecting the credentials, to confirm they are accepted before saving — distinguishing "Cisco rejected these" from "Cisco could not be reached." | +| Advisory-driven mode | The tool's existing behaviour: given an advisory or Event Response link, determine which inventory firewalls are affected, using AI to interpret the advisory. | +| Inventory-driven mode | The behaviour this BRD defines: given the inventory, determine which firewalls Cisco lists as vulnerable and to what. | +| Cisco PSIRT advisory service | Cisco's official published source of security advisory data, the same data behind Cisco's public Software Checker; the authority for every verdict in this mode. | +| Software Checker | Cisco's public web tool that returns the advisories affecting a chosen product, hardware platform, and software release — the manual equivalent of this mode. | +| Product family | The Cisco software line a device runs, e.g. ASA, FTD, FMC; determines how Cisco is queried. | +| Hardware platform | The Cisco appliance series a device is, e.g. the ISA 3000 series or the Secure Firewall 3100 series; required alongside the release because the same release affects platforms differently. | +| Release | The software version a device runs. Cisco publishes a canonical identifier that may differ in form from how the inventory records it. | +| Advisory | A published Cisco security notice, identified by a `cisco-sa-…` identifier, carrying a severity, CVE identifiers, and the release that fixes it. | +| Fixed release | The first Cisco release in which an advisory's vulnerability is resolved; the remediation target for an affected device. | +| Severity | Cisco's security impact rating for an advisory — Critical, High, Medium, Low, or Informational. | +| Impacted | Cisco lists at least one advisory as applying to that device's release on that device's platform. Not a claim that the device is exploitable. | +| Not impacted | Cisco recognises both the release and the platform and lists no applicable advisories. | +| Needs review | A trustworthy verdict could not be established, with a stated reason. Explicitly not a claim of safety. | +| Coverage cut-off | The publication date before which Cisco's checker data holds no advisories for a given product family, bounding what this mode can find. | +| Request quota | Cisco's published ceiling on how many requests an application may make per second, minute, and day. | +| Work products | User-owned outputs and inputs — generated reports and the firewall inventory — which this mode reads or adds to but never destroys. | diff --git a/specs/006-api-inventory-check/checklists/requirements.md b/specs/006-api-inventory-check/checklists/requirements.md new file mode 100644 index 0000000..e254791 --- /dev/null +++ b/specs/006-api-inventory-check/checklists/requirements.md @@ -0,0 +1,54 @@ +# Specification Quality Checklist: Inventory-Driven Vulnerability Check via the Cisco PSIRT API + +**Purpose**: Validate specification completeness and quality before proceeding to planning +**Created**: 2026-07-25 +**Feature**: [spec.md](../spec.md) + +## Content Quality + +- [x] No implementation details (languages, frameworks, APIs) +- [x] Focused on user value and business needs +- [x] Written for non-technical stakeholders +- [x] All mandatory sections completed + +## Requirement Completeness + +- [x] No [NEEDS CLARIFICATION] markers remain +- [x] Requirements are testable and unambiguous +- [x] Success criteria are measurable +- [x] Success criteria are technology-agnostic (no implementation details) +- [x] All acceptance scenarios are defined +- [x] Edge cases are identified +- [x] Scope is clearly bounded +- [x] Dependencies and assumptions identified + +## Feature Readiness + +- [x] All functional requirements have clear acceptance criteria +- [x] User scenarios cover primary flows +- [x] Feature meets measurable outcomes defined in Success Criteria +- [x] No implementation details leak into specification + +## Notes + +- Items marked incomplete require spec updates before `/speckit-clarify` or `/speckit-plan` + +### Validation record + +**Iteration 1** — three issues found and corrected before this checklist was marked complete: + +1. **Implementation detail leaked into requirements.** The first draft named HTTP status codes and the specific Cisco endpoint paths when describing how an unrecognised release is told apart from one that never shipped on a model. Rewritten as observable outcomes (FR-011, FR-012, FR-019) with the mechanism deferred to `/speckit-plan`. +2. **Two success criteria were not measurable.** "The report is easy to act on" and "credentials are handled safely" were replaced with SC-005/SC-006 (every Impacted device lists an advisory with a working link and a fixed release) and SC-011 (no credential value in any output across successful, failed and interrupted runs). +3. **`--api` interaction with existing flags was unspecified.** Added FR-003 (mutual exclusion with the advisory-driven mode) and FR-004 (existing inventory and output options honoured) after noticing US1 had no scenario for conflicting invocation; scenario 10 was added to US1 to cover it. + +**Zero `[NEEDS CLARIFICATION]` markers.** Every open question carried by BRD-003 was resolvable from the BRD's own resolutions, the project constitution, or a documented reasonable default. Each default is recorded in the spec's Assumptions section so it can be challenged. The two most consequential: + +- **No release substitution and no platform-agnostic fallback** (FR-013). The project's non-negotiable conservative-analysis principle supplies the default: asking Cisco about a release or platform the device does not actually have, then reporting that answer as the device's verdict, is a guess. Devices in that situation are Needs review. This is the single decision most likely to be revisited, because it produces Needs review rows for end-of-support releases Cisco has purged from its catalogue. +- **Coverage limited to ASA, FTD and FMC first**, with any other family becoming Needs review rather than failing the run. + +### Items carried to `/speckit-plan` + +Neither blocks specification approval; both are governance work the planning phase must record: + +- **New external endpoints.** The mode contacts Cisco authentication and advisory hosts the analyzer does not contact today. The constitution's Technology & Data Constraints treat any additional endpoint as a reviewed change, so it needs a recorded amendment. +- **Verdict vocabulary.** This mode uses `Needs review`; the existing mode's report and the constitution's Principle IV use `Indeterminate` for the same conservative posture. Either align the labels or record the divergence deliberately. diff --git a/specs/006-api-inventory-check/spec.md b/specs/006-api-inventory-check/spec.md new file mode 100644 index 0000000..6dd4c20 --- /dev/null +++ b/specs/006-api-inventory-check/spec.md @@ -0,0 +1,271 @@ +# Feature Specification: Inventory-Driven Vulnerability Check via the Cisco PSIRT API + +**Feature Branch**: `006-api-inventory-check` + +**Created**: 2026-07-25 + +**Status**: Draft + +**Input**: BRD-003 — `brds/003-api-inventory-check.md` (Inventory-Driven Vulnerability Check via the Cisco PSIRT API, `caia --api`) + +## User Scenarios & Testing *(mandatory)* + +### User Story 1 - Assess the whole inventory in one command (Priority: P1) + +An analyst has their firewall inventory in the folder they are working in and Cisco API access already available. They run the tool with the `--api` option and nothing else. The tool loads the inventory, asks Cisco which published advisories apply to each device's software release on that device's hardware model, and writes a single timestamped HTML report naming every firewall they own alongside a verdict of Impacted, Not impacted, or Needs review. No advisory link is required and no AI service is involved. + +Critically, a device is only ever called Not impacted when Cisco positively confirms both that it recognises the release and that the release runs on that model. Anything else is Needs review, never a claim of safety. + +**Why this priority**: This is the entire point of the feature and the minimum viable slice — it turns an exercise nobody performs (checking a thousand devices by hand in a web form) into one command. It carries the safety rule for negatives because a version of this that could report an unanswerable device as safe would be more dangerous than no report at all, so that rule cannot be deferred to a later slice. + +**Independent Test**: Run the tool with `--api` against a fixture inventory containing devices known to be affected, devices known to be clean, and devices whose release or model Cisco does not recognise. Confirm a report is produced, every inventory row appears exactly once with exactly one verdict, affected devices list their advisories, and no unanswerable device is labelled Not impacted. + +**Acceptance Scenarios**: + +1. **Given** a valid inventory and available Cisco API access, **When** the analyst runs the tool with `--api`, **Then** a new timestamped HTML report is created in the output folder and its location is reported to the analyst. +2. **Given** a completed run, **When** the report is opened, **Then** every row of the source inventory appears exactly once, retains its original columns, and carries exactly one verdict. +3. **Given** Cisco returns one or more advisories for a device's release on its model, **When** the verdict is assigned, **Then** the device is Impacted and those advisories are listed against it. +4. **Given** Cisco confirms both the release and the model and returns no applicable advisories, **When** the verdict is assigned, **Then** and only then is the device Not impacted. +5. **Given** Cisco does not recognise a device's release, or does not list that release as running on that device's model, **When** the verdict is assigned, **Then** the device is Needs review and never Not impacted. +6. **Given** a request to Cisco fails or returns an answer the tool cannot interpret, **When** the verdict is assigned, **Then** the device is Needs review and never Not impacted. +7. **Given** a report already exists in the output folder, **When** a new run writes its report, **Then** the existing report is left intact and the new report is written alongside it. +8. **Given** many devices share the same product family, model and release, **When** the run executes, **Then** Cisco is asked once for that combination and the answer is applied to every device sharing it. +9. **Given** the analyst runs the tool without `--api`, **When** it executes, **Then** the existing advisory-driven behaviour and its spreadsheet report are unchanged. +10. **Given** the analyst supplies both `--api` and an advisory URL, **When** the tool starts, **Then** it reports that the two modes are mutually exclusive and makes no requests. + +--- + +### User Story 2 - Know exactly why a device could not be assessed (Priority: P1) + +An analyst reads the report to decide what needs no action, and an inventory owner reads it to find what to correct. Every Needs review device states, in plain language, which situation applies: Cisco does not recognise the release at all; Cisco recognises the release but does not list it for that model; the model could not be identified as a Cisco hardware platform; a required inventory field is missing; the product family cannot be checked; or the check did not complete. Where Cisco does list the release for other models, those models are named, so the reader can see immediately whether the inventory records the wrong model or the wrong release. + +**Why this priority**: A feasibility check against the real inventory found 15 of 70 rows unanswerable — end-of-support releases Cisco has purged, and model/release pairings Cisco never shipped. A bare "Needs review" on a fifth of the fleet is noise that gets ignored; a specific, correctable reason turns the same rows into an actionable data-quality worklist, and is what makes the verdict trustworthy rather than merely cautious. + +**Independent Test**: Run against a fixture inventory containing one device of each unanswerable kind. Confirm each is Needs review, each carries a distinct reason naming its situation, and the release-not-listed case names the models Cisco does list for that release. + +**Acceptance Scenarios**: + +1. **Given** a device whose release Cisco does not recognise at all, **When** the report is read, **Then** it states that Cisco does not recognise that release, and shows the release as recorded in the inventory. +2. **Given** a device whose release Cisco recognises but does not list for that device's model, **When** the report is read, **Then** it says so and names the models Cisco does list for that release. +3. **Given** a device whose model cannot be identified as a Cisco hardware platform, **When** the report is read, **Then** it states that the model could not be identified. +4. **Given** a device whose check did not complete, **When** the report is read, **Then** it states that the check did not complete for that device. +5. **Given** a release recorded in operational shorthand rather than Cisco's canonical form, **When** it is checked, **Then** it is reconciled to Cisco's equivalent release and assessed, not reported as unrecognised. +6. **Given** any Needs review device, **When** the report is read, **Then** its reason is understandable without consulting the tool's authors or its source code. + +--- + +### User Story 3 - Act on the findings without leaving the report (Priority: P2) + +A patching engineer opens the report and narrows it to what matters — Impacted devices, highest priority first. For any device they expand its advisories and see, for each, how severe it is and which release fixes it. The advisory identifier links straight to Cisco's published advisory. All of this works from the file alone, including on a machine with no network access and after the file has been emailed on. + +**Why this priority**: Without this the report is a list of problems rather than a worklist. It is P2 because the verdicts themselves (P1) already carry the safety-critical information; this slice is what makes acting on them efficient rather than manual. + +**Independent Test**: Open a report produced from a fixture run on a machine with no network connection. Filter to Impacted, sort by the inventory's priority column, expand a device with many advisories, and confirm each advisory shows severity and fixed release and that its identifier is a link to Cisco. + +**Acceptance Scenarios**: + +1. **Given** the report is open, **When** the reader filters by verdict, **Then** only devices with that verdict remain visible. +2. **Given** the report is open, **When** the reader sorts by the inventory's priority column, **Then** the rows reorder accordingly. +3. **Given** a device with many advisories, **When** its detail is collapsed, **Then** the device's row remains readable at a glance, and expanding it reveals the full advisory list. +4. **Given** a listed advisory, **When** the reader looks at it, **Then** its identifier, title and severity are shown, its identifier links to Cisco's published advisory, and the release that first fixes it is shown whenever Cisco supplies one. +5. **Given** the report file has been copied or emailed to another machine with no network access, **When** it is opened, **Then** its layout, filtering, sorting and expanding all still work. + +--- + +### User Story 4 - Set up and validate Cisco API access once (Priority: P2) + +An analyst runs the tool's configuration command. In one linear pass it prompts for everything the tool uses, including the two Cisco API values. The client identifier is shown as they paste it; the client secret is not displayed, and immediately after entry the tool confirms that a value was captured and how many characters it held, so a truncated paste is obvious. Any prompt can be skipped by someone who does not need it. Once both Cisco values are in hand, the tool checks them against Cisco and says plainly whether they work — and if Cisco cannot be reached at all, it says that instead of calling them invalid, and lets them be saved unverified. Later runs from any folder find them without re-entry. + +**Why this priority**: Setup is a precondition for the feature, but it is P2 because a run can be exercised with Cisco access supplied through the environment, so the primary slice can be built and tested before the guided flow exists. Validating at setup rather than mid-run is what keeps a bad paste from being discovered as a failed run against a thousand devices. + +**Independent Test**: Run the configuration command with no Cisco values saved. Confirm both are prompted, the identifier echoes and the secret does not, the length confirmation appears, correct values report as valid, deliberately wrong values report Cisco's reason and offer re-entry, and an unreachable Cisco reports distinctly and permits saving unverified. + +**Acceptance Scenarios**: + +1. **Given** the analyst runs the configuration command, **When** the flow runs, **Then** it prompts for the Cisco client identifier and the Cisco client secret alongside the settings it already collects, and saves them to the per-user configuration. +2. **Given** the analyst is prompted for the client identifier, **When** they paste it, **Then** it is displayed as entered; **and given** they are prompted for the client secret, **When** they paste it, **Then** it is not displayed in readable form. +3. **Given** a secret has just been entered, **When** the prompt completes, **Then** the tool confirms a value was captured and how many characters it contained, without revealing the value. +4. **Given** a Cisco value is already saved, **When** the analyst is prompted for it, **Then** the tool indicates a value exists and an empty response leaves it unchanged. +5. **Given** both Cisco values are available, **When** Cisco accepts them, **Then** the tool states plainly that the credentials are valid. +6. **Given** both Cisco values are available, **When** Cisco rejects them, **Then** the tool reports the reason Cisco gave, offers to enter them again, and does not silently save the rejected values. +7. **Given** both Cisco values are available, **When** Cisco cannot be reached at all, **Then** the tool distinguishes this from a rejection and lets the analyst save the values unverified with a clear warning. +8. **Given** the analyst skipped the Cisco prompts, **When** the flow completes, **Then** no verification request is made to Cisco. +9. **Given** verification succeeds, fails, or cannot run, **When** any message is shown, **Then** it contains no part of either credential value. +10. **Given** Cisco values were saved by the configuration command, **When** the analyst runs `--api` from a different folder, **Then** the run proceeds without re-entering them. +11. **Given** the analyst uses only the advisory-driven mode, **When** they run the configuration command, **Then** they can complete it without supplying Cisco values, and that mode still runs. +12. **Given** the analyst uses only `--api`, **When** they run it, **Then** it does not require the AI service key to be configured. +13. **Given** no Cisco values are available, **When** the analyst runs `--api`, **Then** the tool refuses to run, names what is missing, directs them to the configuration command, and makes no requests to Cisco. +14. **Given** the saved values are rejected by Cisco, **When** a run starts, **Then** the tool reports an authentication problem distinctly from "no advisories apply" and produces no verdicts. + +--- + +### User Story 5 - Judge how far to trust a report you did not run (Priority: P3) + +A team lead receives a report second-hand. Before acting on it they can see when it ran, which inventory file it came from, how many devices were assessed, and the count for each verdict — including how many could not be assessed at all. The same summary states the known limits of the underlying Cisco data: that it holds no advisories published before Cisco's per-family cut-off dates, and that a verdict reflects whether a release is listed as affected, not whether a vulnerable feature is switched on. + +**Why this priority**: It prevents the most likely misuse of the report — treating it as a complete and exploitability-aware picture. It is P3 because the report is still correct without it; this slice makes it correctly *interpreted*. + +**Independent Test**: Open a report from a fixture run and confirm the summary carries the run timestamp, the inventory filename, the device count, a count per verdict, and both coverage statements — without reading any device row. + +**Acceptance Scenarios**: + +1. **Given** any report, **When** it is opened, **Then** it shows the run date and time, the inventory file used, the number of devices assessed, and a count for each verdict. +2. **Given** any report, **When** it is read, **Then** it states that the underlying Cisco data excludes advisories published before Cisco's per-family cut-off dates. +3. **Given** any report, **When** it is read, **Then** it states that a verdict does not account for whether a vulnerable feature is enabled on the device. +4. **Given** a report containing Needs review devices, **When** it is read, **Then** their count is visible in the summary rather than only discoverable row by row. + +--- + +### Edge Cases + +- **A release genuinely absent from Cisco's catalogue while a shorter form of it exists.** The tool does not substitute a different release than the device runs; the device is Needs review. A verdict obtained by asking about a release the device is not running would be a guess. +- **A model that maps to no Cisco hardware platform.** The device is Needs review; the tool does not fall back to a platform-agnostic question whose answer could apply to hardware the device is not. +- **A product family the mode cannot check.** Every device in that family is Needs review with that stated reason; the run still completes for the rest. +- **An inventory row with a blank or missing release, or a blank model.** Needs review, naming the missing field. +- **An empty inventory, or one with no usable rows.** The run stops with an actionable message rather than producing an empty report. +- **Every device ends as Needs review.** The run is a success — a report was produced — and the summary makes the wholly inconclusive result obvious. Exit status reflects whether the run completed, not what the verdicts were. +- **Cisco becomes unreachable partway through a run.** Devices already answered keep their verdicts; the remainder are Needs review stating the check did not complete, and the report discloses that the run was partial. +- **Cisco's request quota is reached mid-run.** Treated as an incomplete check: remaining devices are Needs review and the report says the run was cut short. +- **Cisco returns a response shape the tool does not recognise.** Needs review rather than a guessed verdict. +- **A device impacted by a very large number of advisories.** The device's row stays readable and the full list remains reachable; the report does not silently truncate it. +- **Two runs completing within the same second.** Both reports survive; neither overwrites the other. +- **The output folder does not exist or cannot be written.** The tool reports the problem and the path it attempted, rather than losing the run's results silently. +- **The analyst interrupts a long run.** The tool stops promptly and signals interruption through its exit status. +- **A credential present but empty, or carrying surrounding whitespace.** Treated as not supplied rather than sent to Cisco as-is. +- **Advisory text from Cisco containing markup or scripting.** Rendered as text; it cannot alter the report's structure or behaviour. + +## Requirements *(mandatory)* + +### Functional Requirements + +**Mode and invocation** + +- **FR-001**: The tool MUST provide an `--api` option that assesses the loaded inventory against Cisco's published advisory data per device, requiring no advisory or Event Response URL. +- **FR-002**: The tool MUST leave the existing advisory-driven mode, including its spreadsheet report, unchanged in behaviour and output when `--api` is not supplied. +- **FR-003**: The tool MUST treat `--api` and the advisory-driven mode as mutually exclusive, reporting an actionable message and making no requests when both are requested in one invocation. +- **FR-004**: The `--api` mode MUST honour the tool's existing inventory-selection and output-location options, so a run can be fully flag-driven without interactive input. +- **FR-005**: The `--api` mode MUST make no call to the AI service and MUST NOT require the AI service credential. +- **FR-006**: The tool SHOULD offer a way to exercise an `--api` run without contacting Cisco — resolving each device to the check that would be made and reporting it — so the flow can be verified cheaply and offline. + +**Verdict assignment and integrity** + +- **FR-007**: The tool MUST assign every row of the inventory exactly one verdict from: Impacted, Not impacted, Needs review. +- **FR-008**: The tool MUST classify a device Impacted only when Cisco returns at least one advisory applying to that device's release on that device's hardware platform. +- **FR-009**: The tool MUST classify a device Not impacted only when Cisco positively confirms both that it recognises the release and that it lists that release for the device's hardware platform, and returns no applicable advisories. +- **FR-010**: The tool MUST classify a device Needs review whenever a trustworthy verdict cannot be established, and MUST NOT classify such a device Not impacted. +- **FR-011**: The tool MUST distinguish, in the reason recorded for a Needs review device, at least these situations: the release is not in Cisco's catalogue; the release is in the catalogue but not listed for that platform; the model could not be identified as a Cisco platform; a required inventory field is missing; the product family cannot be checked; and the check did not complete. +- **FR-012**: When a release is not listed for a device's platform, the tool MUST name the platforms Cisco does list for that release. +- **FR-013**: The tool MUST NOT substitute a different release, or a platform-agnostic question, in place of the device's actual release and platform in order to obtain a verdict. +- **FR-014**: The tool MUST distinguish an authentication, connectivity, or quota failure from a "no advisories apply" answer, and MUST NOT derive any Not impacted verdict from a failed or incomplete exchange. +- **FR-015**: The tool MUST treat a response it cannot interpret as Needs review rather than inferring a verdict from it. +- **FR-016**: When a run cannot assess every device, the tool MUST still produce a report for the devices it did assess, mark the remainder Needs review, and disclose in the report that the run was partial. + +**Reconciling the inventory with Cisco's data** + +- **FR-017**: The tool MUST reconcile inventory release strings recorded in operational shorthand with Cisco's canonical release identifiers, including releases carrying a companion-product annotation or a build suffix. +- **FR-018**: The tool MUST determine each device's Cisco hardware platform from its inventory model. +- **FR-019**: The tool MUST obtain, from Cisco at run time rather than from a fixed built-in list, the set of valid hardware platforms per product family and the set of releases Cisco recognises together with the platforms each runs on. +- **FR-020**: The tool MUST ask Cisco once per distinct combination of product family, hardware platform and release, and apply that answer to every device sharing the combination. +- **FR-021**: The tool MUST continue to tolerate minor variation in the inventory's column headings, as it does today. + +**Report content and behaviour** + +- **FR-022**: The tool MUST produce exactly one self-contained report per run, readable in a web browser, written to the tool's output folder with a timestamped name. +- **FR-023**: The tool MUST never overwrite an existing report, including when two runs complete within the same second. +- **FR-024**: The report MUST list every analysed device exactly once, retaining the inventory's original columns, alongside its verdict. +- **FR-025**: The report MUST list, for each Impacted device, the advisories that justify the verdict, and MUST NOT silently truncate that list. +- **FR-026**: The report MUST show, for each listed advisory, its identifier, its title, its severity, and a link to Cisco's published advisory, and MUST show the release that first fixes it whenever Cisco supplies one. +- **FR-027**: The report SHOULD show the CVE identifiers Cisco associates with each listed advisory. +- **FR-028**: The report MUST state, for each Needs review device, the reason it could not be assessed. +- **FR-029**: The report MUST let a reader filter by verdict, sort by the inventory's priority column, and expand or collapse a device's advisory detail, using the file alone with no external tool and no network access. +- **FR-030**: The report MUST render and remain fully functional after being copied or emailed to another machine, and when opened with no network connectivity. +- **FR-031**: The report MUST state the run date and time, the inventory file used, the number of devices assessed, and a count for each verdict. +- **FR-032**: The report MUST state that the underlying Cisco data excludes advisories published before Cisco's per-family cut-off dates, and that a verdict does not account for whether a vulnerable feature is enabled. +- **FR-033**: The tool MUST render all content received from Cisco as text, such that it cannot alter the report's structure, styling, or behaviour. + +**Credentials and configuration** + +- **FR-034**: The configuration command MUST prompt for the Cisco client identifier and the Cisco client secret alongside the settings it already collects, in a single linear pass. +- **FR-035**: The configuration command MUST allow any individual prompt to be skipped, and MUST NOT require a value for a mode the user does not use. +- **FR-036**: Each mode MUST require only its own credentials: `--api` MUST NOT require the AI service key, and the advisory-driven mode MUST NOT require Cisco credentials. +- **FR-037**: The configuration command MUST display the Cisco client identifier as it is entered, and MUST NOT display the Cisco client secret in readable form. +- **FR-038**: The configuration command MUST confirm, immediately after a secret is entered, that a value was captured and how many characters it contained, without revealing the value. +- **FR-039**: The configuration command SHOULD give visible feedback while a secret is being entered where the terminal supports it, and MUST fall back to a non-displaying prompt where it does not. +- **FR-040**: The configuration command MUST indicate when a Cisco value is already saved, and MUST leave it unchanged when the user submits an empty response. +- **FR-041**: The configuration command MUST verify the Cisco credentials with Cisco before completing, and MUST state plainly whether they are valid. +- **FR-042**: When Cisco rejects the credentials, the configuration command MUST report the reason Cisco gave, MUST offer to enter them again, and MUST NOT silently save the rejected values. +- **FR-043**: When Cisco cannot be reached to verify, the configuration command MUST distinguish this from a rejection and MUST allow the values to be saved unverified with a clear warning, so a network or proxy outage never prevents configuration. +- **FR-044**: The configuration command MUST attempt verification only when both Cisco values are available for the session, and MUST make no request to Cisco when those prompts were skipped. +- **FR-045**: The tool MUST store the Cisco credentials in the same per-user configuration it already uses, with the same protection, so later runs from any folder find them without re-entry. +- **FR-046**: The tool MUST continue to honour Cisco credentials supplied through the environment, taking precedence over saved values. +- **FR-047**: The tool MUST treat an empty or whitespace-only credential as not supplied. +- **FR-048**: The tool MUST refuse to start an `--api` run when Cisco credentials are unavailable, naming what is missing, directing the user to the configuration command, and making no requests to Cisco. +- **FR-049**: The tool MUST NOT display, log, or write any part of a credential value — in the report, in printed output, in an error or warning message, or in any filename it creates. + +**Run behaviour, pacing and outcome** + +- **FR-050**: The tool MUST operate within Cisco's published request quotas for a full-inventory run, pacing its own requests rather than relying on the user to throttle. +- **FR-051**: The tool MUST report progress during a run so a full-inventory run does not appear stalled. +- **FR-052**: The tool MUST signal the outcome of a run through its exit status, distinguishing a completed run from a failure, and MUST signal interruption distinctly when the analyst stops a run. +- **FR-053**: The tool MUST treat a run in which every device ends as Needs review as a completed run rather than a failure, provided a report was written. +- **FR-054**: The tool MUST report an actionable message, naming the path it attempted, when the output folder cannot be created or written. +- **FR-055**: The tool MUST stop with an actionable message, rather than producing an empty report, when the inventory has no usable rows. + +**Documentation** + +- **FR-056**: The documentation MUST explain that `--api` produces a browser-readable report while the default mode produces a spreadsheet, and why the two modes answer different questions. +- **FR-057**: The documentation MUST list the Cisco API credentials among the prerequisites a new user obtains before first use, and MUST show the configuration command as the way to supply them. + +### Key Entities + +- **Device**: One row of the user's inventory. Carries a name, a model, a product family, a software release, and a priority. Every device receives exactly one verdict and, where applicable, a reason. +- **Check**: A distinct combination of product family, hardware platform and release, derived from one or more devices. The unit Cisco is actually asked about, so identical devices cost one question rather than many. +- **Verdict**: One of Impacted, Not impacted, or Needs review. Not impacted asserts that Cisco confirmed the device is clean; Needs review asserts nothing about safety and always carries a reason. +- **Reason**: The plain-language explanation attached to a Needs review verdict, identifying which situation applies and, where relevant, the platforms Cisco does list for the release. +- **Advisory**: A published Cisco security notice associated with a Check. Carries an identifier, a title, a severity, CVE identifiers, a link to its published page, and the release that first fixes it. +- **Platform catalogue**: The set of hardware platforms Cisco recognises per product family, retrieved at run time, used to map an inventory model to something Cisco can be asked about. +- **Release catalogue**: The set of releases Cisco recognises together with the platforms each runs on, retrieved at run time, used to tell an unrecognised release apart from a release that never shipped on that model. +- **Report**: The single self-contained per-run artifact. Carries the run summary, the coverage statements, and one entry per device with its verdict, reason and advisories. +- **Cisco credentials**: A client identifier and a client secret, held in the per-user configuration or the environment, used only to obtain access to Cisco's advisory data and never surfaced in output. + +## Success Criteria *(mandatory)* + +### Measurable Outcomes + +- **SC-001**: An analyst can assess the entire firewall inventory with a single command and no advisory link, producing one report. +- **SC-002**: 100% of inventory rows appear in the report exactly once with exactly one verdict; no row is silently dropped. +- **SC-003**: 0% of devices whose release or model Cisco does not recognise are reported as Not impacted. +- **SC-004**: 100% of Needs review devices carry a reason identifying which situation applies, understandable without consulting the tool's authors. +- **SC-005**: 100% of Impacted devices list at least one advisory, and every listed advisory carries a working link to its published Cisco page. +- **SC-006**: Every listed advisory for which Cisco supplies a fixed release shows that release, so an engineer obtains the remediation target without a further lookup. +- **SC-007**: A run against an inventory of approximately 1,000 devices completes within Cisco's request quotas and produces a complete report. +- **SC-008**: An inventory of approximately 1,000 devices results in substantially fewer questions to Cisco than it has rows, because identical devices are asked about once. +- **SC-009**: Repeated runs never overwrite an earlier report; each run leaves a distinct, durable file. +- **SC-010**: A report renders, filters, sorts and expands correctly when opened with no network access and after being copied to another machine. +- **SC-011**: No credential value appears in any report, printed output, message, or filename, across successful, failed and interrupted runs. +- **SC-012**: A run started without Cisco credentials, or with credentials Cisco rejects, produces a clear diagnostic and no verdicts. +- **SC-013**: A new user can go from having their Cisco credentials in hand to a completed `--api` run using only the configuration command and the run command, without creating a file or setting an environment variable. +- **SC-014**: A user of only one mode can configure and run that mode without supplying the other mode's credentials. +- **SC-015**: A wrong, truncated, or expired Cisco credential is detected during configuration rather than on a later run, and the user is told why. +- **SC-016**: Configuration remains completable when Cisco cannot be reached, with the unverified state disclosed rather than the setup being blocked. +- **SC-017**: After entering the client secret, a user can tell from the confirmation alone whether their paste landed intact, without the value being displayed. +- **SC-018**: Every report states its coverage limits, so a reader who did not run it can judge how far to trust it. +- **SC-019**: A partial run is never presented as complete: the report discloses that some devices were not assessed. +- **SC-020**: Running the tool without `--api` produces the same result it did before this feature existed. + +## Assumptions + +- **Credential source.** Because the tool is installed as a command run from arbitrary working folders, the interactive configuration command is in practice the only credential path a user exercises. A working-folder environment file is an automation convenience this feature does not rely on; environment variables remain honoured but are not the expected route. +- **Credential ownership.** Each user obtains their own Cisco API client identifier and secret from Cisco's developer portal, exactly as each user already obtains their own AI service key. The tool does not provision or share them. +- **Inventory shape.** The inventory keeps its current form: one row per firewall with a name, model, product family, software release and priority, in a user-provided spreadsheet located in the working folder. +- **Families covered first.** The product families present in the inventory today — ASA, FTD and FMC — are the families this mode must handle. Devices in any family the mode cannot check become Needs review with that reason, so the run still completes; extending coverage to further families Cisco supports is a later increment. +- **No release substitution.** When a device's release is absent from Cisco's catalogue, the tool does not fall back to asking about a shorter or nearby release. This follows the project's non-negotiable conservative-analysis principle: a verdict obtained by asking about a release the device is not running would be a guess. The device is Needs review instead — honest, but it will produce Needs review rows for end-of-support releases Cisco has purged. +- **No platform-agnostic fallback.** Likewise, a model that maps to no Cisco platform is Needs review rather than being asked about without a platform, since a platform-agnostic answer could reflect hardware the device is not. +- **Catalogues fetched per run.** The platform and release catalogues are retrieved fresh on each run rather than cached between runs, so a newly published release is never missed. Their cost is a small fixed number of questions independent of inventory size. +- **Identical devices share a verdict.** Devices with the same product family, platform and release receive the same answer, so one question serves many devices and a large inventory collapses to far fewer questions than rows. +- **Cisco is the authority.** Cisco's published data decides whether a release on a platform is affected. The tool reports that answer and does not second-guess it, which also means the mode inherits Cisco's coverage cut-offs. +- **Impacted is not exploitability.** An Impacted verdict means the release on that platform is listed as affected. Whether the vulnerable feature is switched on is not knowable from the inventory and is out of scope; the report says so. +- **Report is opened by the user.** The tool writes a file and reports its location; it does not launch a browser or host the report. Reports accumulate in the output folder as they do today. +- **Verdict vocabulary.** This mode uses Needs review for an undecidable device, whereas the existing mode's report uses Indeterminate for the same underlying idea. Both express the conservative posture the project's analysis principle requires; aligning the vocabulary across the two modes, or recording the divergence deliberately, is a governance item for the planning phase rather than a change in behaviour here. +- **New external endpoints.** This mode contacts Cisco authentication and advisory endpoints the tool does not contact today. The project's constraints treat any additional endpoint the analyzer contacts as a reviewed change, so the planning phase must record these before implementation. +- **Offline verification.** FR-006 (exercising a run without contacting Cisco) derives from the project's existing quality gate that user-facing changes to analysis flow should be verifiable without network calls. It was not requested in the BRD, but it keeps this mode testable on the same terms as the existing one. From cb6938ac9f11eb4c8211a0af468deb404f3f56f7 Mon Sep 17 00:00:00 2001 From: Ali Bahaloo Date: Sat, 25 Jul 2026 09:00:03 -0700 Subject: [PATCH 2/5] docs(006): plan and design artifacts; amend constitution to 2.2.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Planning artifacts and a governance amendment — no runtime code changes. Constitution 2.1.0 -> 2.2.0 (MINOR), applied as a prerequisite of spec 006: - Principle IV: the insufficient-data result must be labelled undecided rather than specifically "Indeterminate", with both that label and "Needs review" named as conforming for their respective reports. The AI-normalization clause is scoped to modes that use AI. - Principle IV also now states the positive-confirmation rule explicitly: "not affected" must rest on affirmation from Cisco's data, never on the mere absence of a result, and an undecided device must never be presented as unaffected. Previously implicit; made explicit so the failure mode the spike found cannot be reintroduced. - Networking: admits apix.cisco.com (advisory data, catalogues) and id.cisco.com (access token), with a new constraint that only the derived family/platform/release triple may be sent — never a firewall name or other inventory identifier. - Source of truth: admits Cisco's PSIRT openVuln API, and requires the platform/release catalogues be retrieved from Cisco rather than hardcoded. - Inputs/outputs: records impact_report_*.html, and makes single-file/offline rendering and never-overwrite constitutional. Phase 0/1 artifacts for spec 006: research.md 15 decisions, each verified against the live API rather than taken from documentation. Two findings the docs do not cover: the API separates "no advisories" (404) from "unknown release" (406) by status code where the reference describes one conflated 200; and /platforms disagrees with /OS_version/OS_data on platform display names (FPRNGFW), so name equality cannot carry a safety decision. data-model.md 9 entities, the 10-row outcome table that is the single source of verdict truth, and the run/exit-status map. contracts/ caia --api CLI, extended caia --config CLI, the external Cisco API contract, and the HTML report contract. quickstart.md Validation scenarios A-K plus the fixture-inventory requirement; Scenario B is the gate. All Constitution Check gates pass unconditionally now that the amendment is applied. Complexity Tracking is empty. Co-Authored-By: Claude Opus 5 --- .specify/memory/constitution.md | 81 ++-- .../contracts/api-run-cli.md | 118 ++++++ .../contracts/config-cli.md | 96 +++++ .../contracts/html-report.md | 128 +++++++ .../contracts/psirt-access.md | 143 +++++++ specs/006-api-inventory-check/data-model.md | 213 +++++++++++ specs/006-api-inventory-check/plan.md | 260 +++++++++++++ specs/006-api-inventory-check/quickstart.md | 178 +++++++++ specs/006-api-inventory-check/research.md | 361 ++++++++++++++++++ 9 files changed, 1555 insertions(+), 23 deletions(-) create mode 100644 specs/006-api-inventory-check/contracts/api-run-cli.md create mode 100644 specs/006-api-inventory-check/contracts/config-cli.md create mode 100644 specs/006-api-inventory-check/contracts/html-report.md create mode 100644 specs/006-api-inventory-check/contracts/psirt-access.md create mode 100644 specs/006-api-inventory-check/data-model.md create mode 100644 specs/006-api-inventory-check/plan.md create mode 100644 specs/006-api-inventory-check/quickstart.md create mode 100644 specs/006-api-inventory-check/research.md diff --git a/.specify/memory/constitution.md b/.specify/memory/constitution.md index 4b17fa1..0847787 100644 --- a/.specify/memory/constitution.md +++ b/.specify/memory/constitution.md @@ -1,20 +1,27 @@