Files
cve-dashboard/.kiro/specs/archer-template-library/tasks.md
Jordan Ramos a61d254ff9 Sync .kiro/ from master — v2.2.0 release batch
New specs: archer-template-library, ccp-metrics-view-restructure,
compliance-list-stale-after-sidebar-edit, compliance-metric-estimated-resolution-date,
compliance-remediation-display-fix, flexible-jira-ticket-creation,
forecast-burndown-chart, granite-loader-export, ivanti-queue-clear-completed-fix,
multi-item-jira-ticket, queue-collapsible-sections, vendor-issue-type-dropdown

New steering: archer-template-gen.md

Updated: migration-registration-check hook, remediation-plan-history spec,
gitlab-workflow, tech, versioning steering files
2026-06-04 11:27:31 -06:00

17 KiB

Implementation Plan: Archer Template Library

Overview

This plan implements the Archer Template Library feature — a template management system for storing and reusing Archer Risk Acceptance form content organized by Vendor > Platform > Model hierarchy. The implementation progresses from database schema, through backend CRUD/search API, to frontend Template Manager page and TemplateSelector integration in the Ivanti Todo Queue workflow.

The backend uses Node.js/Express 5 with PostgreSQL (pool from backend/db.js), following the existing factory-pattern route module convention. The frontend uses React 19 (plain JavaScript) with the project's dark theme aesthetic. Property-based tests use fast-check in backend/__tests__/.

Tasks

  • 1. Database migration and schema setup

    • 1.1 Create the archer_templates table migration
      • Create backend/migrations/add_archer_templates_table.js using the idempotent migration pattern (IF NOT EXISTS)
      • Define the archer_templates table with columns: id SERIAL PRIMARY KEY, vendor VARCHAR(100) NOT NULL, platform VARCHAR(100) NOT NULL, model VARCHAR(100) NOT NULL, 8 TEXT section columns (all NOT NULL DEFAULT ''), created_by INTEGER REFERENCES users(id) ON DELETE SET NULL, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW()
      • Create unique index idx_archer_templates_unique_combo on (LOWER(TRIM(vendor)), LOWER(TRIM(platform)), LOWER(TRIM(model)))
      • Create index idx_archer_templates_vendor on (vendor) and idx_archer_templates_platform on (platform) for list query performance
      • Register the migration in backend/migrations/run-all.js by appending 'add_archer_templates_table.js' to the POSTGRES_MIGRATIONS array
      • Requirements: 1.1, 1.2, 1.3, 1.4, 1.5
  • 2. Backend route module — core CRUD

    • 2.1 Create backend/routes/archerTemplates.js with factory function and create endpoint

      • Create the file following the factory pattern: function createArcherTemplatesRouter() returning an Express Router
      • Import pool from '../db', { requireAuth, requireGroup } from '../middleware/auth', and logAudit from '../helpers/auditLog'
      • Implement POST / — validate vendor/platform/model (required, 1-100 chars after trim, non-empty after trim), validate section fields (max 10,000 chars each, default to empty string), INSERT with RETURNING *, handle unique constraint violation (23505) as 409, call logAudit fire-and-forget on success with action template_created
      • Implement GET / — query all templates with optional search (ILIKE across vendor/platform/model), optional exact-match filters on vendor/platform/model (case-insensitive via LOWER/TRIM), combine with AND logic, ORDER BY vendor, platform, model ASC
      • Implement GET /:id — fetch single template by ID, return 404 if not found
      • Requirements: 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.10, 2.11, 2.12, 6.1, 6.2, 6.3, 6.4, 6.5, 6.6, 8.1
    • 2.2 Implement update, delete, and clone endpoints

      • Implement PUT /:id — validate provided fields (same rules as create), build dynamic UPDATE SET clause for only provided fields, always set updated_at = NOW(), check uniqueness if vendor/platform/model changed (excluding self), return 404/409/400 as appropriate, call logAudit with action template_updated and changed field names
      • Implement DELETE /:id — verify template exists (404 if not), DELETE, call logAudit with action template_deleted and vendor/platform/model of the deleted template, return 200
      • Implement POST /:id/clone — verify source exists (404 if not), validate new vendor/platform/model (required, same rules as create), INSERT copying all 8 section fields from source with new hierarchy values and created_by = req.user.id, handle uniqueness violation as 409, call logAudit with action template_cloned and both source/new IDs
      • Requirements: 2.7, 2.8, 2.9, 2.10, 2.12, 3.1, 3.2, 3.3, 3.4, 3.5, 8.2, 8.3, 8.4, 8.5, 8.6
    • 2.3 Implement hierarchy endpoints (vendors, platforms, models)

      • Implement GET /hierarchy/vendors — SELECT DISTINCT vendor ORDER BY vendor ASC
      • Implement GET /hierarchy/platforms — require vendor query param (400 if missing), SELECT DISTINCT platform WHERE LOWER(TRIM(vendor)) matches, ORDER BY platform ASC
      • Implement GET /hierarchy/models — require vendor and platform query params (400 if either missing), SELECT DISTINCT model WHERE both match, ORDER BY model ASC
      • All hierarchy endpoints require requireAuth() middleware
      • Requirements: 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 7.7
    • 2.4 Wire the router into backend/server.js

      • Add const createArcherTemplatesRouter = require('./routes/archerTemplates'); to the imports section
      • Mount with app.use('/api/archer-templates', createArcherTemplatesRouter()); after the existing archer-tickets route
      • Requirements: 2.10, 2.11
  • 3. Checkpoint - Backend API verification

    • Ensure all tests pass, ask the user if questions arise.
  • 4. Backend property-based tests

    • * 4.1 Write property test for template data round-trip preservation

      • File: backend/__tests__/archer-template-library.property.test.js
      • Property 1: Template data round-trip preservation
      • Generate valid templates with random vendor (1-100 chars), platform (1-100 chars), model (1-100 chars), and section content (0-10,000 chars each); create via POST then GET by ID; assert all fields match (vendor/platform/model trimmed)
      • Minimum 100 iterations
      • Validates: Requirements 1.1, 1.2, 1.5, 2.1
    • * 4.2 Write property test for uniqueness enforcement

      • File: backend/__tests__/archer-template-library.property.test.js
      • Property 2: Uniqueness enforcement across all write operations
      • Generate template pairs with matching LOWER(TRIM(vendor/platform/model)) but varying case/whitespace; assert second create returns 409, update to matching combo returns 409, clone to matching combo returns 409
      • Minimum 100 iterations
      • Validates: Requirements 1.3, 2.2, 2.8, 3.2, 3.5
    • * 4.3 Write property test for input validation

      • File: backend/__tests__/archer-template-library.property.test.js
      • Property 3: Input validation rejects invalid hierarchy fields
      • Generate invalid inputs: empty strings, whitespace-only, strings > 100 chars for vendor/platform/model; assert POST and PUT return 400 with error identifying which field(s) failed
      • Minimum 100 iterations
      • Validates: Requirements 1.6, 2.3
    • * 4.4 Write property test for sorted results

      • File: backend/__tests__/archer-template-library.property.test.js
      • Property 4: List and search results are sorted
      • Generate multiple templates with random hierarchy values, insert all, then GET with various search/filter combos; assert response is sorted by vendor ASC, platform ASC, model ASC (case-insensitive)
      • Minimum 100 iterations
      • Validates: Requirements 2.4, 6.4
    • * 4.5 Write property test for search and filter AND logic

      • File: backend/__tests__/archer-template-library.property.test.js
      • Property 5: Search and filter semantics with AND logic
      • Generate template sets with overlapping vendor/platform/model values; apply combined search substring + field exact-match filters; assert every result satisfies ALL conditions and no matching template is missing
      • Minimum 100 iterations
      • Validates: Requirements 2.5, 2.6, 6.1, 6.2, 6.3
    • * 4.6 Write property test for partial update preservation

      • File: backend/__tests__/archer-template-library.property.test.js
      • Property 6: Partial update preserves unspecified fields
      • Generate a template, then PUT with a random subset of fields; assert unmodified fields remain unchanged and updated_at is updated
      • Minimum 100 iterations
      • Validates: Requirements 2.7
    • * 4.7 Write property test for delete permanence

      • File: backend/__tests__/archer-template-library.property.test.js
      • Property 7: Delete removes template permanently
      • Generate a template, DELETE it, then GET by ID; assert 404 response
      • Minimum 100 iterations
      • Validates: Requirements 2.9
    • * 4.8 Write property test for access control

      • File: backend/__tests__/archer-template-library.property.test.js
      • Property 8: Write operations require editor or admin role
      • Generate write operation requests (POST/PUT/DELETE/clone) with viewer-role or unauthenticated sessions; assert all are rejected with 401 or 403
      • Minimum 100 iterations
      • Validates: Requirements 2.10, 4.13
    • * 4.9 Write property test for non-existent ID handling

      • File: backend/__tests__/archer-template-library.property.test.js
      • Property 9: Non-existent template ID returns 404
      • Generate random IDs that don't exist; assert GET, PUT, DELETE, and clone all return 404
      • Minimum 100 iterations
      • Validates: Requirements 2.12, 3.4
    • * 4.10 Write property test for clone content preservation

      • File: backend/__tests__/archer-template-library.property.test.js
      • Property 10: Clone preserves all section content
      • Generate a template with random section content, clone with new hierarchy values; assert all 8 section fields are byte-for-byte identical, ID differs, created_at is new, created_by matches requesting user
      • Minimum 100 iterations
      • Validates: Requirements 3.1, 3.3
    • * 4.11 Write property test for hierarchy distinct values

      • File: backend/__tests__/archer-template-library.property.test.js
      • Property 11: Hierarchy endpoints return distinct sorted values
      • Generate templates with overlapping vendors/platforms/models; assert vendors endpoint returns deduplicated sorted array, platforms for a vendor returns only that vendor's platforms sorted, models for vendor+platform returns only matching models sorted
      • Minimum 100 iterations
      • Validates: Requirements 7.1, 7.2, 7.3
    • * 4.12 Write property test for Copy All concatenation format

      • File: backend/__tests__/archer-template-library.property.test.js
      • Property 12: Copy All concatenation format
      • Generate templates with random mix of populated and empty sections; construct the expected "Copy All" output (only non-empty sections, with headers, static first then semi-static); assert the concatenation matches expected format and order
      • Minimum 100 iterations
      • Validates: Requirements 5.9
  • 5. Checkpoint - Backend tests pass

    • Ensure all tests pass, ask the user if questions arise.
  • 6. Frontend Template Manager page

    • 6.1 Create frontend/src/components/pages/ArcherTemplatePage.js with list view

      • Create the page component following the project's dark-theme inline-styles pattern
      • Implement template list fetch on mount from GET /api/archer-templates
      • Display templates grouped by vendor, then platform, with collapsible vendor groups
      • Show vendor, platform, and model for each template row
      • Conditionally render create/edit/clone/delete buttons using useAuth() role check (hide for viewer role)
      • Requirements: 4.1, 4.2, 4.13
    • 6.2 Implement TemplateFormModal (create/edit/clone)

      • Create a modal component (inline in ArcherTemplatePage.js or as a separate subcomponent)
      • Include fields for vendor (max 100 chars), platform (max 100 chars), model (max 100 chars), and all 8 section content textareas with human-readable labels
      • For create mode: all fields empty; for edit mode: pre-populate from template; for clone mode: pre-populate sections from source, leave hierarchy fields empty
      • Client-side validation: prevent submission with empty vendor/platform/model, show which required fields are missing
      • On submit: POST for create/clone, PUT for edit; handle 409 conflict errors by displaying the conflict message from API
      • On success: close modal and refresh template list
      • Requirements: 4.3, 4.4, 4.8, 4.9, 4.10, 4.11, 4.12
    • 6.3 Implement DeleteConfirmModal and delete flow

      • Create a confirmation dialog that identifies the template by vendor/platform/model
      • On confirm: call DELETE API, remove template from displayed list, close dialog
      • On cancel: dismiss dialog, leave template unchanged
      • Requirements: 4.5, 4.6, 4.7
    • 6.4 Wire ArcherTemplatePage into navigation

      • Add a navigation entry in NavDrawer.js for the Template Manager page
      • Add the page routing in App.js (following the existing page-switching pattern)
      • Requirements: 4.1
  • 7. Frontend TemplateSelector component

    • 7.1 Create frontend/src/components/TemplateSelector.js with searchable dropdown

      • Create the reusable component that fetches templates from GET /api/archer-templates
      • Implement search input that filters the template list (case-insensitive substring match on vendor/platform/model — client-side filter for responsiveness)
      • Display templates in dropdown as Vendor / Platform / Model label
      • Requirements: 5.1, 5.2
    • 7.2 Implement section display panel and copy functionality

      • When a template is selected, display all populated sections in a panel
      • Order: static sections first (Environment Overview, Segmentation, Mitigating Controls), then semi-static sections (Additional Info/Background, Charter Network Banner, Data Classification, Charter Network, Additional Access List)
      • Display each section with human-readable label (not DB column name)
      • Show copy-to-clipboard button adjacent to each section; disable for empty sections (show muted "No content stored" placeholder)
      • On copy: use navigator.clipboard.writeText(), show checkmark/"Copied!" for 2 seconds then revert
      • Implement "Copy All" button: concatenate all non-empty sections with section headers, copy combined text
      • Requirements: 5.3, 5.4, 5.5, 5.6, 5.7, 5.8, 5.9
    • 7.3 Integrate TemplateSelector into IvantiTodoQueuePage

      • Embed the TemplateSelector component in IvantiTodoQueuePage.js when viewing an Archer workflow queue item
      • Display as an expandable panel within the Archer queue item view
      • Requirements: 5.1
  • 8. Checkpoint - Frontend build and integration verification

    • Run cd frontend && npm run build to verify no ESLint or build errors
    • Ensure all tests pass, ask the user if questions arise.
  • 9. Backend unit and integration tests

    • * 9.1 Write unit tests for template CRUD operations

      • File: backend/__tests__/archer-template-library.test.js
      • Test template creation with all sections populated returns 201 with full record
      • Test template creation with no sections defaults to empty strings
      • Test timestamp metadata correctness (created_at, updated_at, created_by set properly)
      • Test clone metadata (new created_at, new created_by, different ID)
      • Test hierarchy endpoint without required params returns 400
      • Test empty search results return 200 with empty array
      • Test whitespace-only search param is ignored (returns all templates)
      • Test authentication required for read endpoints (401 without session)
      • Requirements: 1.1, 1.2, 1.4, 1.5, 2.1, 2.3, 2.4, 2.11, 2.12, 3.1, 3.3, 6.5, 6.6, 7.4, 7.5, 7.6
    • * 9.2 Write integration tests for audit logging and full workflow

      • File: backend/__tests__/archer-template-library.integration.test.js
      • Test audit log entries created for create/update/delete/clone operations
      • Test audit log failure does not block template operation (mock logAudit to throw)
      • Test failed operations (400, 409, 404) do not produce audit entries
      • Test full workflow: create → list → update → clone → delete
      • Requirements: 8.1, 8.2, 8.3, 8.4, 8.5, 8.6
  • 10. Final checkpoint - Full test suite passes

    • Ensure all tests pass, ask the user if questions arise.

Notes

  • Tasks marked with * are optional test sub-tasks and can be skipped for a faster MVP.
  • Each task references specific requirements for traceability.
  • Property tests use fast-check with a minimum of 100 iterations and are tagged per the design's Testing Strategy.
  • The migration must be registered in run-all.js to be picked up by CI/CD deploys.
  • The route module follows the existing createArcherTicketsRouter() pattern in routes/archerTickets.js.
  • Frontend styling follows the dark-theme tactical intelligence aesthetic defined in DESIGN_SYSTEM.md.
  • Checkpoints (tasks 3, 5, 8, 10) ensure incremental validation at each layer.

Task Dependency Graph

{
  "waves": [
    { "id": 0, "tasks": ["1.1"] },
    { "id": 1, "tasks": ["2.1"] },
    { "id": 2, "tasks": ["2.2", "2.3"] },
    { "id": 3, "tasks": ["2.4"] },
    { "id": 4, "tasks": ["4.1", "4.2", "4.3", "4.4", "4.5", "4.6", "4.7", "4.8", "4.9", "4.10", "4.11", "4.12"] },
    { "id": 5, "tasks": ["6.1", "7.1"] },
    { "id": 6, "tasks": ["6.2", "6.3", "7.2"] },
    { "id": 7, "tasks": ["6.4", "7.3"] },
    { "id": 8, "tasks": ["9.1", "9.2"] }
  ]
}