WORKFLOWS.md

June 13, 2026 ยท View on GitHub

Hack23 Logo

๐Ÿ”„ Riksdagsmonitor โ€” CI/CD Workflows

๐Ÿ”ง DevSecOps Pipeline and Automation Documentation
๐ŸŽฏ Multi-Stage Quality Gates for Security, Quality, and Reliability

Owner Version Last Updated Review Cycle

๐Ÿ“‹ Document Owner: CEO | ๐Ÿ“„ Version: 7.6 | ๐Ÿ“… Last Updated: 2026-05-28 (UTC) ๐Ÿ”„ Review Cycle: Quarterly | โฐ Next Review: 2026-08-05 ๐Ÿข Owner: Hack23 AB (Org.nr 5595347807) | ๐Ÿท๏ธ Classification: Public


๐Ÿ“Š Workflow Status Badges

CI/CD & Security

Quality Checks Dependency Review CodeQL Scorecard supply-chain security OpenSSF Scorecard

Testing & Quality

TypeScript & JavaScript Testing TypeDoc Validation Translation Validation Knip Dead Code Check

Documentation & Release

Release API Docs Test Coverage


๐ŸŽฏ Purpose & Scope

This document provides comprehensive documentation of the CI/CD workflows implemented in the Riksdagsmonitor project, demonstrating alignment with Hack23 ISMS Secure Development Policy ยง10.1 "CI/CD Workflow & Automation Excellence". It serves as evidence of automated security operations, pipeline transparency, and continuous security validation.

Compliance Objectives:

  • ISO 27001 (A.12.1): Change management documentation and controls
  • NIST CSF (DE.CM): Continuous monitoring and detection evidence
  • CIS Controls (17.1): Implement and manage automated secure application deployments
  • Transparency: Public demonstration of security automation and quality gates

The project has been migrated from JavaScript to TypeScript (31 modules in src/browser/) with all workflows updated accordingly. TypeScript compilation is handled by Vite (esbuild) for browser bundles and Node 26's native type-stripping for scripts.

Total Workflow Files: 54 (26 standard YAML + 14 agentic .md sources + 14 compiled .lock.yml). Each agentic workflow consists of a source .md file and its compiled .lock.yml counterpart, yielding 40 distinct workflows (26 standard + 14 agentic). Security Compliance: 100% (all actions SHA-pinned, harden-runner enabled)

๐Ÿ” ISMS Policy Alignment

Riksdagsmonitor's CI/CD workflows implement security controls mandated by Hack23 AB's ISMS framework:

ISMS PolicyWorkflow Implementation
๐Ÿ› ๏ธ Secure Development PolicySAST (CodeQL), SCA (Dependency Review), quality gates, coverage thresholds
๐Ÿ“ Change ManagementAutomated testing gates, security scanning, PR review requirements
๐Ÿ” Vulnerability ManagementDependabot, CodeQL, OpenSSF Scorecard, security advisories
๐Ÿ”“ Open Source PolicySLSA attestations, SBOM generation, license compliance
๐Ÿ” Information Security PolicySecurity-hardened runners, SHA-pinned actions, least privilege permissions
๐ŸŒ Network Security PolicyEgress auditing via harden-runner, HTTPS-only endpoints
๐Ÿ”‘ Access Control PolicyLeast privilege workflow permissions, OIDC token usage
๐Ÿ”’ Cryptography PolicyTLS 1.3 enforcement, SRI for CDN assets, SLSA provenance
DocumentFocusDescriptionDocumentation Link
Architecture๐Ÿ›๏ธ ArchitectureC4 model showing current system structureView Source
Future Architecture๐Ÿ›๏ธ ArchitectureArchitectural evolution roadmap (2026โ€“2037)View Source
Security Architecture๐Ÿ›ก๏ธ SecurityDefense-in-depth security controlsView Source
Threat Model๐Ÿ›ก๏ธ SecuritySTRIDE threat analysis and risk assessmentView Source
Data Model๐Ÿ“Š DataData structures and relationshipsView Source
Flowcharts๐Ÿ”„ ProcessBusiness process and data flowsView Source
State Diagrams๐Ÿ”„ BehaviorSystem state transitions and lifecyclesView Source
Mindmaps๐Ÿง  ConceptSystem conceptual relationshipsView Source
SWOT Analysis๐Ÿ’ผ BusinessStrategic assessmentView Source
Future Workflows๐Ÿ”ง DevOpsEnhanced CI/CD vision (2026โ€“2037)View Source
Future Security Architecture๐Ÿ›ก๏ธ SecuritySecurity roadmapView Source
CRA Assessment๐Ÿ›ก๏ธ ComplianceEU Cyber Resilience Act conformityView Source
End-of-Life Strategy๐Ÿ“… LifecycleMaintenance and EOL planningView Source

๐Ÿ—๏ธ Pipeline Architecture

The Riksdagsmonitor project implements a comprehensive DevSecOps CI/CD pipeline with multi-stage quality gates:

graph LR
    A[Code Push] --> B[Build & Test]
    B --> C[SCA Scan]
    C --> D[CodeQL Scan]
    D --> E[Quality Gate]
    E --> F[Security Gate]
    F --> G[SBOM Generation]
    G --> H[Attestations]
    H --> I[Release]
    I --> J[Dual Deploy]

    classDef trigger fill:#bbdefb,stroke:#1565c0,stroke-width:2px,color:black
    classDef build fill:#c8e6c9,stroke:#2e7d32,stroke-width:2px,color:black
    classDef security fill:#ffccbc,stroke:#bf360c,stroke-width:2px,color:black
    classDef quality fill:#fff9c4,stroke:#f57f17,stroke-width:2px,color:black
    classDef attestation fill:#d1c4e9,stroke:#4a148c,stroke-width:2px,color:black
    classDef deploy fill:#a5d6a7,stroke:#1b5e20,stroke-width:2px,color:black

    class A trigger
    class B build
    class C,D security
    class E quality
    class F security
    class G,H attestation
    class I,J deploy

Pipeline Stages Summary

StageTool/ServiceTriggerQuality GateDuration
๐Ÿ—๏ธ Build & TestVite, Vitest, CypressPush/PRTests pass, coverage thresholds enforced at the Hack23 Secure Development Policy floor (statements โ‰ฅ80 % / branches โ‰ฅ70 % / functions โ‰ฅ70 % / lines โ‰ฅ80 %; see vitest.config.js and TESTING.md for measured baseline)~3.4s build, ~63s test
๐Ÿ“ฆ SCADependabot, Dependency ReviewDaily / PRNo critical vulnerabilities~2 min
๐Ÿ” CodeQLGitHub CodeQLPR, Push, WeeklyNo critical/high issues~10 min
โœ… Quality GateESLint, HTMLHint, linkinatorEvery commitZero errors, valid HTML~3 min
๐Ÿ”’ Security Gateharden-runner (enforced), Scorecard (advisory)Every commitZero critical vulnerabilities in enforced checks; Scorecard advisory onlyAuto
๐Ÿ“‹ SBOMRelease attestationReleaseComplete SBOM generated~2 min
๐Ÿ” AttestationsGitHub AttestationsReleaseSLSA provenance created~2 min
๐Ÿš€ Dual DeployAWS S3/CloudFront + GitHub PagesRelease / PushSuccessful build artifact~3 min

Technology Stack

ComponentVersionPurpose
GitHub Actions Runnerubuntu-26.04CI/CD execution environment
Node.js26Runtime (native TypeScript strip-types)
TypeScript6.0.3Type system
Vite8.0.14Build toolchain (esbuild)
Vitest4.1.7Unit testing (7,500+ tests)
Cypress15.16.0E2E testing (optional dependency)
TypeDoc0.28.18API documentation
ESLint10.xLinting (flat config)

๐Ÿ• Agentic Workflow Daily Schedule

The agentic news workflows run on a precisely orchestrated daily schedule (all times UTC):

flowchart TD
    subgraph Morning["๐ŸŒ… Morning Analysis"]
        A["CIA Stats Update<br/>02:00 ยท 60 min"]
        B["Committee Reports<br/>04:00 ยท 90 min"]
        C["Government Propositions<br/>05:00 ยท 90 min"]
        D["Opposition Motions<br/>06:00 ยท 90 min"]
        E["Interpellation Debates<br/>07:00 ยท 90 min"]
    end

    subgraph Midday["๐Ÿ“ฐ Midday Monitoring"]
        F["Realtime Monitor AM<br/>10:00 ยท 120 min"]
        G["Translation Batch AM<br/>11:00 ยท 90 min"]
    end

    subgraph Evening["๐ŸŒ† Afternoon / Evening"]
        H["Realtime Monitor PM<br/>14:00 ยท 120 min"]
        I["Translation Batch PM<br/>17:00 ยท 90 min"]
        J["Evening Analysis<br/>18:00 ยท 120 min"]
    end

    A --> B --> C --> D --> E --> F --> G --> H --> I --> J

Weekend Schedule Variations

DayActive WorkflowsSchedule Difference
SaturdayWeekly Review (09:00) ยท Realtime Monitor (12:00) ยท Evening/Weekly Wrap-up (16:00) ยท Translation (14:00)Reduced frequency; weekly synthesis
SundayRealtime Monitor (12:00) ยท Translation (14:00)Minimal coverage
1st of MonthMonth Ahead (08:00) ยท Quarter Ahead (09:00)Monthly + quarterly strategic outlook
15th of MonthQuarter Ahead (09:00)Mid-month quarterly refresh
28th of MonthMonthly Review (10:00)Monthly retrospective
FridayWeek Ahead (07:00)Weekly prospective outlook
5 Jan / 5 JulYear Ahead (09:00)Semi-annual strategic outlook anchored in IMF WEO vintage
13 Mar / 13 SepElection Cycle (dispatch-only)Delivered: semi-annual election-cycle deep intelligence (cron declared but disabled)

๐Ÿ”„ Workflow Overview

The Riksdagsmonitor project uses 54 workflow files (26 standard .yml + 14 agentic .lock.yml + 14 agentic .md sources) organized into 5 functional categories:

graph TB
    subgraph "๐Ÿ” Security & Compliance"
        SEC1["๐Ÿ›ก๏ธ CodeQL<br/><i>SAST scanning</i>"]
        SEC2["๐Ÿ“ฆ Dependency Review<br/><i>Supply chain</i>"]
        SEC3["๐Ÿ“Š Scorecard<br/><i>OSSF scoring</i>"]
        SEC4["๐Ÿ” Quality Checks<br/><i>TypeScript lint</i>"]
        SEC5["๐Ÿท๏ธ Setup Labels<br/><i>PR labeling</i>"]
    end

    subgraph "๐Ÿงช Testing"
        TEST1["๐Ÿ  Test Homepage<br/><i>Cypress E2E</i>"]
        TEST2["๐Ÿ“Š Test Dashboard<br/><i>Cypress E2E</i>"]
        TEST3["๐Ÿ“ฐ Test News<br/><i>Cypress E2E</i>"]
        TEST4["๐Ÿ”ฌ JS/TS Testing<br/><i>Vitest unit</i>"]
    end

    subgraph "๐Ÿš€ Deployment"
        DEP1["โ˜๏ธ Deploy S3<br/><i>Production</i>"]
        DEP2["๐Ÿ”– Release<br/><i>Attestations</i>"]
        DEP3["๐ŸŒ Uptime Monitor<br/><i>Every 15 min</i>"]
    end

    subgraph "๐Ÿ“Š Data Pipeline"
        DATA1["๐Ÿ“Š Update CIA CSV Data<br/><i>Nightly 03:30 UTC + manual</i>"]
    end

    subgraph "๐Ÿ“ฐ Agentic News (14 workflows)"
        NEWS1["๐Ÿ“‹ Committee Reports<br/><i>Mon-Fri 04:00</i>"]
        NEWS2["๐Ÿ“œ Propositions<br/><i>Mon-Fri 05:00</i>"]
        NEWS3["โœŠ Motions<br/><i>Mon-Fri 06:00</i>"]
        NEWS4["โ“ Interpellations<br/><i>Mon-Fri 07:00</i>"]
        NEWS5["โšก Realtime Monitor<br/><i>2-3ร— daily</i>"]
        NEWS6["๐ŸŒ™ Evening Analysis<br/><i>Mon-Fri 18:00</i>"]
        NEWS7["๐Ÿ“… Week Ahead<br/><i>Friday 07:00</i>"]
        NEWS8["๐Ÿ“Š Weekly Review<br/><i>Saturday 09:00</i>"]
        NEWS9["๐Ÿ“… Month Ahead<br/><i>1st 08:00</i>"]
        NEWS10["๐Ÿ“Š Monthly Review<br/><i>28th 10:00</i>"]
        NEWS11["๐ŸŒ Translate<br/><i>2-3ร— daily</i>"]
        NEWS12["๐Ÿ“ Quarter Ahead<br/><i>1st+15th 09:00</i>"]
        NEWS13["๐Ÿ“† Year Ahead<br/><i>5 Jan+Jul 09:00</i>"]
        NEWS14["๐Ÿ—ณ๏ธ Election Cycle<br/><i>Dispatch only</i>"]
    end

    NEWS1 & NEWS2 & NEWS3 & NEWS4 & NEWS5 & NEWS6 -->|"dispatch"| NEWS11
    NEWS7 & NEWS8 & NEWS9 & NEWS10 -->|"dispatch"| NEWS11

    style SEC1 fill:#dc3545,color:#fff,stroke:#b02a37
    style SEC2 fill:#dc3545,color:#fff,stroke:#b02a37
    style SEC3 fill:#dc3545,color:#fff,stroke:#b02a37
    style SEC4 fill:#dc3545,color:#fff,stroke:#b02a37
    style SEC5 fill:#dc3545,color:#fff,stroke:#b02a37
    style TEST1 fill:#0d6efd,color:#fff,stroke:#0a58ca
    style TEST2 fill:#0d6efd,color:#fff,stroke:#0a58ca
    style TEST3 fill:#0d6efd,color:#fff,stroke:#0a58ca
    style TEST4 fill:#0d6efd,color:#fff,stroke:#0a58ca
    style DEP1 fill:#198754,color:#fff,stroke:#146c43
    style DEP2 fill:#198754,color:#fff,stroke:#146c43
    style DEP3 fill:#198754,color:#fff,stroke:#146c43
    style DATA1 fill:#6f42c1,color:#fff,stroke:#59359a
    style DATA2 fill:#6f42c1,color:#fff,stroke:#59359a
    style DATA3 fill:#6f42c1,color:#fff,stroke:#59359a
    style DATA4 fill:#6f42c1,color:#fff,stroke:#59359a
    style DATA5 fill:#6f42c1,color:#fff,stroke:#59359a
    style NEWS1 fill:#fd7e14,color:#fff,stroke:#ca6510
    style NEWS2 fill:#fd7e14,color:#fff,stroke:#ca6510
    style NEWS3 fill:#fd7e14,color:#fff,stroke:#ca6510
    style NEWS4 fill:#fd7e14,color:#fff,stroke:#ca6510
    style NEWS5 fill:#ffc107,color:#000,stroke:#cc9a06
    style NEWS6 fill:#d63384,color:#fff,stroke:#ab296a
    style NEWS7 fill:#20c997,color:#000,stroke:#1aa179
    style NEWS8 fill:#20c997,color:#000,stroke:#1aa179
    style NEWS9 fill:#0dcaf0,color:#000,stroke:#0aa2c0
    style NEWS10 fill:#0dcaf0,color:#000,stroke:#0aa2c0
    style NEWS11 fill:#e9ecef,color:#212529,stroke:#adb5bd
    style NEWS12 fill:#6c757d,color:#fff,stroke:#495057

Core CI/CD Workflows

  1. โœ… Quality Checks (.github/workflows/quality-checks.yml) โ€” ESLint linting, HTML validation, link checking
  2. ๐Ÿงน Knip Dead Code Check (.github/workflows/knip.yml) โ€” Detects unused files, dependencies, binaries, and duplicate exports on every PR (informational pass also reports unused exports/types)
  3. ๐Ÿงช TypeScript & JavaScript Testing (.github/workflows/javascript-testing.yml) โ€” Vitest unit tests, TypeScript type-checking, Cypress E2E
  4. ๐Ÿ“– TypeDoc Validation (.github/workflows/jsdoc-validation.yml) โ€” API documentation generation and coverage
  5. ๐ŸŒ Translation Validation (.github/workflows/translation-validation.yml) โ€” 14-language validation with RTL and hreflang
  6. ๐Ÿš€ Release with Attestations (.github/workflows/release.yml) โ€” SLSA provenance, SBOM, dual deployment
  7. โ˜๏ธ Deploy to S3 (.github/workflows/deploy-s3.yml) โ€” AWS S3/CloudFront deployment

Security Scanning Workflows

  1. ๐Ÿ” CodeQL Analysis (.github/workflows/codeql.yml) โ€” SAST for JavaScript/TypeScript vulnerabilities
  2. ๐Ÿ“ฆ Dependency Review (.github/workflows/dependency-review.yml) โ€” SCA for dependency vulnerabilities
  3. โญ Scorecard Analysis (.github/workflows/scorecards.yml) โ€” OpenSSF supply chain security assessment

Testing & Monitoring Workflows

  1. ๐Ÿ–ฅ๏ธ Test Dashboard (.github/workflows/test-dashboard.yml) โ€” Dashboard Cypress E2E tests
  2. ๐Ÿ  Test Homepage (.github/workflows/test-homepage.yml) โ€” Homepage Cypress E2E tests
  3. ๐Ÿ“ฐ Test News (.github/workflows/test-news.yml) โ€” News pages Cypress E2E tests
  4. ๐Ÿ”† Lighthouse CI (.github/workflows/lighthouse-ci.yml) โ€” Performance, accessibility, SEO auditing
  5. ๐Ÿ“ก Uptime Monitor (.github/workflows/uptime-monitor.yml) โ€” 15-minute availability checks for all 14 languages

CIA Data Pipeline Workflows

  1. ๐Ÿ“Š Update CIA CSV Data (.github/workflows/update-cia-csv-data.yml) โ€” Nightly + manual refresh of every already-tracked data/cia/** and cia-data/** CSV from upstream Hack23/cia service.data.impl/sample-data/ (recursive basenameโ†’path index, handles sub-folders); also refreshes cia-data/production-stats.json and injects counts into index*.html; opens a single PR when anything changes

Automation & Infrastructure Workflows

  1. ๐Ÿท๏ธ Setup Labels (.github/workflows/setup-labels.yml) โ€” Repository label management
  2. ๐Ÿท๏ธ PR Labeler (.github/workflows/labeler.yml) โ€” Automated PR labeling
  3. ๐Ÿ”ง Compile Agentic Workflows (.github/workflows/compile-agentic-workflows.yml) โ€” Compile .md โ†’ .lock.yml
  4. ๐Ÿค– Copilot Setup Steps (.github/workflows/copilot-setup-steps.yml) โ€” GitHub Copilot environment

๐Ÿค– Agentic News Workflows (14 workflows: each has a .md source + .lock.yml compiled output)

  1. ๐Ÿ“ฐ News Committee Reports โ€” Committee report coverage
  2. ๐Ÿ“ฐ News Propositions โ€” Government proposition coverage
  3. ๐Ÿ“‹ News Motions โ€” Parliamentary motion tracking
  4. โ“ News Interpellations โ€” Interpellation debate tracking
  5. ๐ŸŒ… News Evening Analysis โ€” Evening analysis reports
  6. ๐Ÿ“ก News Realtime Monitor โ€” Real-time political monitoring
  7. ๐Ÿ”ฎ News Week Ahead โ€” Upcoming week preview
  8. ๐Ÿ“… News Month Ahead โ€” Upcoming month preview
  9. ๐Ÿ“Š News Quarter Ahead โ€” 90-day parliamentary-season forecast
  10. ๐Ÿ“ˆ News Year Ahead โ€” 365-day annual outlook (PESTLE blocking)
  11. ๐Ÿ—ณ๏ธ News Election Cycle โ€” Full 4-year mandate analysis (dispatch-only)
  12. ๐Ÿ“Š News Weekly Review โ€” Weekly political summary
  13. ๐Ÿ“† News Monthly Review โ€” Monthly political review
  14. ๐ŸŒ News Translate โ€” Multi-language article translation

Workflow Relationships

flowchart TB
    subgraph "๐Ÿ”„ Continuous Integration"
        direction TB
        PR[Pull Request] --> CodeQLScan[๐Ÿ” CodeQL Analysis]
        PR --> DependencyReview[๐Ÿ“ฆ Dependency Review]
        PR --> Labeler[๐Ÿท๏ธ PR Labeler]
        PR --> QualityChecks[โœ… Quality Checks]
        PR --> TranslationVal[๐ŸŒ Translation Validation]
        CodeQLScan --> SecurityEvents[๐Ÿ›ก๏ธ Security Events]
    end

    subgraph "๐Ÿงช Testing Pipeline"
        direction TB
        PR --> UnitTests[๐Ÿงช TypeScript & JS Testing]
        UnitTests --> TypeCheck[TSC Type Check]
        UnitTests --> Vitest[Vitest 7500+ Tests]
        UnitTests --> CypressE2E[Cypress E2E]
        PR --> DashboardE2E[๐Ÿ–ฅ๏ธ Dashboard E2E]
        PR --> HomepageE2E[๐Ÿ  Homepage E2E]
        PR --> NewsE2E[๐Ÿ“ฐ News E2E]
    end

    subgraph "๐Ÿ“Š CIA Data Pipeline"
        direction TB
        Schedule1[โฐ Nightly 03:30 UTC] --> CIACsv[๐Ÿ“Š Update CIA CSV Data]
        ManualTrig[๐Ÿ–ฑ Manual dispatch] --> CIACsv
        CIACsv --> CIAPR[๐Ÿ” Open PR on changes]
    end

    subgraph "๐Ÿš€ Continuous Deployment"
        direction TB
        Release[Release Trigger] --> Build[๐Ÿ—๏ธ Vite Build]
        Build --> Attestations[๐Ÿ” SLSA Attestations]
        Attestations --> DualDeploy{Dual Deploy}
        DualDeploy --> S3Deploy[โ˜๏ธ AWS S3/CloudFront]
        DualDeploy --> GHPages[๐Ÿ“„ GitHub Pages]
    end

    subgraph "๐Ÿค– Agentic News Generation"
        direction TB
        AgenticTrigger[โฐ Scheduled / Manual] --> NewsGen[๐Ÿ“ฐ 14 News Workflows]
        NewsGen --> Translate[๐ŸŒ Translation]
        Translate --> ContentDeploy[๐Ÿ“ค Content Deploy]
    end

    subgraph "๐Ÿ“ก Monitoring"
        direction TB
        Cron15[โฐ Every 15 min] --> Uptime[๐Ÿ“ก Uptime Monitor]
        WeeklyLH[โฐ Weekly] --> Lighthouse[๐Ÿ”† Lighthouse CI]
        WeeklyScore[โฐ Weekly] --> Scorecard[โญ Scorecard]
    end

    PR -.-> |"approved & merged"| main[Main Branch]
    main --> S3Deploy
    main -.-> |"tag created"| Release

    classDef integration fill:#a0c8e0,stroke:#1565c0,stroke-width:1.5px,color:black
    classDef testing fill:#c8e6c9,stroke:#2e7d32,stroke-width:1.5px,color:black
    classDef deployment fill:#bbdefb,stroke:#1565c0,stroke-width:1.5px,color:black
    classDef security fill:#ffccbc,stroke:#bf360c,stroke-width:1.5px,color:black
    classDef datapipeline fill:#d1c4e9,stroke:#4a148c,stroke-width:1.5px,color:black
    classDef agentic fill:#e1bee7,stroke:#6a1b9a,stroke-width:1.5px,color:black
    classDef monitoring fill:#ffecb3,stroke:#f57f17,stroke-width:1.5px,color:black
    classDef process fill:#c8e6c9,stroke:#2e7d32,stroke-width:1.5px,color:black

    class PR,CodeQLScan,DependencyReview,Labeler,QualityChecks,TranslationVal integration
    class UnitTests,TypeCheck,Vitest,CypressE2E,DashboardE2E,HomepageE2E,NewsE2E testing
    class Release,Build,Attestations,DualDeploy,S3Deploy,GHPages deployment
    class SecurityEvents security
    class Schedule1,Schedule2,CIAStats,SchemaCheck,DataValidation,SchemaSync datapipeline
    class AgenticTrigger,NewsGen,Translate,ContentDeploy agentic
    class Cron15,WeeklyLH,WeeklyScore,Uptime,Lighthouse,Scorecard monitoring
    class main process

๐Ÿ“Š Security Gates & Quality Thresholds

Security GateThresholdWorkflowEnforcement
TypeScript CompilationZero errorsjavascript-testing.ymlRequired โœ…
ESLintZero errorsquality-checks.ymlRequired โœ…
HTMLHint ValidationZero errorsquality-checks.ymlRequired โœ…
Link IntegrityZero broken internal linksquality-checks.ymlRequired โœ…
Knip Dead Code (files/deps/dups)Zero unused files, deps, binaries, or duplicate exportsknip.ymlRequired โœ…
Unit Test Pass Rate100% (7,500+ tests)javascript-testing.ymlRequired โœ…
CodeQL SASTNo critical/highcodeql.ymlRequired โœ…
Dependency VulnerabilitiesNo critical/highdependency-review.ymlRequired โœ…
Translation CompletenessAll 14 languages validtranslation-validation.ymlRequired โœ…
OSSF ScorecardScore > 7.0scorecards.ymlAdvisory โ„น๏ธ
Lighthouse PerformanceScore 90+lighthouse-ci.ymlAdvisory โ„น๏ธ
Site Availability99.9% uptimeuptime-monitor.ymlAdvisory โ„น๏ธ

๐Ÿ” Security Hardening Practices

Riksdagsmonitor implements industry best practices for securing CI/CD pipelines, with StepSecurity hardening for all workflows:

flowchart LR
    subgraph "๐Ÿ›ก๏ธ Pipeline Security Hardening"
        PH[๐Ÿ”’ Permissions Hardening] --> LAP[Least Access Principle]
        PS[๐Ÿ“Œ Pin SHA Versions] --> IDT[Immutable Dependencies]
        AV[โœ… Action Verification] --> TS[Trusted Sources]
        RH[๐Ÿ›ก๏ธ Runner Hardening] --> AL[Audit Logging]
        OT[๐Ÿ”‘ OIDC Tokens] --> EF[Ephemeral Credentials]
    end

    subgraph "๐Ÿ”’ Security Measures"
        AS[๐Ÿ“‹ Asset Security] --> AC[Asset Verification]
        DS[๐Ÿ“ฆ Dependency Security] --> PD[Dependency Pinning]
        BS[๐Ÿ—๏ธ Build Security] --> BA[Build Attestations]
        RS[๐Ÿ“ค Release Security] --> SBOM[SBOM Generation]
    end

    PH --> AS
    PS --> DS
    AV --> BS
    RH --> RS

    classDef security fill:#e74c3c,stroke:#c0392b,stroke-width:1.5px,color:white
    classDef measures fill:#9b59b6,stroke:#8e44ad,stroke-width:1.5px,color:white

    class PH,PS,AV,RH,OT security
    class AS,DS,BS,RS measures

Specific Hardening Measures

Every workflow in the Riksdagsmonitor project implements least-privilege security. The baseline minimum permission is contents: read; individual workflows add only the extra scopes they need (e.g., id-token: write for OIDC, pages: write for deployments, pull-requests: write for PR comments):

  1. ๐Ÿ”’ Permissions Restriction: Explicit least-privilege permissions per workflow

    # Baseline minimum โ€” additional scopes added per-workflow as needed
    permissions:
      contents: read
    
  2. ๐Ÿ“Œ SHA Pinning: All external actions pinned to specific SHA hashes for immutability

    - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
    
  3. ๐Ÿ›ก๏ธ Runner Hardening: StepSecurity harden-runner for egress auditing

    - name: Harden Runner
      uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
      with:
        egress-policy: audit
    
  4. ๐Ÿ“„ SBOM Generation: Software Bill of Materials for supply chain transparency

  5. ๐Ÿ” Build Attestations: SLSA build provenance attestations (via GitHub Attestations)

  6. โฑ๏ธ Timeout Limits: Jobs use timeout limits where applicable to prevent resource exhaustion

  7. ๐Ÿ”‘ OIDC Tokens: Ephemeral authentication for AWS deployments


๐Ÿ“‹ Detailed Pipeline Stages

๐Ÿงช Stage 1: Quality Checks (quality-checks.yml)

Purpose: Validates code quality through ESLint linting, HTML validation, and link checking. Trigger: Push/PR to main Security Controls: Harden-runner with egress auditing, SHA-pinned actions, least privilege permissions (contents: read)

flowchart TD
    Start[๐Ÿš€ Code Push/PR] --> Prepare[๐Ÿ”ง Setup Environment]
    Prepare --> ParallelChecks[Run Checks in Parallel]

    ParallelChecks --> TSLint[๐Ÿ“ TypeScript Lint]
    ParallelChecks --> HTMLVal[๐Ÿ” HTML Validation]
    ParallelChecks --> LinkCheck[๐Ÿ”— Link Checking]

    TSLint --> TSResult{ESLint Pass?}
    HTMLVal --> HTMLResult{HTMLHint Pass?}
    LinkCheck --> LinkResult{Links Valid?}

    TSResult -->|Yes| Summary[๐Ÿ“‹ Summary]
    HTMLResult -->|Yes| Summary
    LinkResult -->|Yes| Summary

    TSResult -->|No| FixCode[โŒ Fix Code]
    HTMLResult -->|No| FixHTML[โŒ Fix HTML]
    LinkResult -->|No| FixLinks[โŒ Fix Links]

    classDef startEnd fill:#3498db,stroke:#2980b9,stroke-width:2px,color:white
    classDef process fill:#34495e,stroke:#2c3e50,stroke-width:2px,color:white
    classDef test fill:#27ae60,stroke:#1e8449,stroke-width:1.5px,color:white
    classDef decision fill:#f39c12,stroke:#e67e22,stroke-width:2px,color:black
    classDef fail fill:#e74c3c,stroke:#c0392b,stroke-width:2px,color:white

    class Start,Summary startEnd
    class Prepare,ParallelChecks process
    class TSLint,HTMLVal,LinkCheck test
    class TSResult,HTMLResult,LinkResult decision
    class FixCode,FixHTML,FixLinks fail

Jobs:

  • ๐Ÿ“ TypeScript Lint โ€” ESLint flat config with @typescript-eslint/parser across tsconfig.browser.json + tsconfig.scripts.json
  • ๐Ÿ” HTML Validation โ€” HTMLHint on all *.html files (14 language versions)
  • ๐Ÿ”— Link Checking โ€” Vite preview server + linkinator recursive check (skip external)

๐Ÿงช Stage 2: TypeScript & JavaScript Testing (javascript-testing.yml)

Purpose: Primary test workflow โ€” TypeScript type-checking, Vitest unit tests, Vite build verification, and multi-language Cypress E2E. Trigger: Push/PR on **/*.ts, **/*.js, src/browser/**, tsconfig*.json, *.html, cypress/**, package*.json

flowchart TD
    CodeChange[๐Ÿ“ Code Change] --> PrepareJob[๐Ÿ”ง Prepare Environment]
    PrepareJob --> TypeCheck[๐Ÿ“‹ TypeScript Type Check]
    TypeCheck --> BrowserTSC[Browser: tsc --noEmit]
    TypeCheck --> ScriptsTSC[Scripts: tsc --noEmit]

    BrowserTSC --> UnitTests[๐Ÿงช Vitest Unit Tests]
    ScriptsTSC --> UnitTests
    UnitTests --> CoverageMeasurement[๐Ÿ“Š Coverage Report]

    PrepareJob --> BuildValidation[๐Ÿ—๏ธ Vite Build]
    BuildValidation --> BuildPass{Build Success?}
    BuildPass -->|Yes| E2ETests[๐ŸŒ Cypress E2E Tests]
    BuildPass -->|No| FixBuild[โŒ Fix Build]

    E2ETests --> UIValidation[๐Ÿ–ผ๏ธ UI Validation]

    CoverageMeasurement --> Report[๐Ÿ“ค Upload Reports]
    UIValidation --> Report

    classDef start fill:#3498db,stroke:#2980b9,stroke-width:2px,color:white
    classDef process fill:#34495e,stroke:#2c3e50,stroke-width:2px,color:white
    classDef test fill:#27ae60,stroke:#1e8449,stroke-width:1.5px,color:white
    classDef decision fill:#9b59b6,stroke:#8e44ad,stroke-width:2px,color:white
    classDef parallel fill:#e67e22,stroke:#d35400,stroke-width:2px,color:white
    classDef fail fill:#e74c3c,stroke:#c0392b,stroke-width:2px,color:white

    class CodeChange start
    class PrepareJob,TypeCheck,BrowserTSC,ScriptsTSC process
    class UnitTests,CoverageMeasurement,E2ETests,UIValidation test
    class BuildPass decision
    class BuildValidation parallel
    class FixBuild fail
    class Report start

TypeScript Compilation Strategy:

  • tsconfig.browser.json โ€” validates src/browser/**/*.ts (31 modules)
  • tsconfig.scripts.json โ€” validates scripts/**/*.ts + tests/**/*.ts
  • Both use noEmit: true (Vite/esbuild handles actual compilation)

Test Coverage: 7,500+ unit tests (Vitest) + Happy-DOM environment for browser modules + V8 coverage provider


๐Ÿ” Stage 3: Security Scanning

3.1 CodeQL Analysis (codeql.yml)

Tool: GitHub CodeQL Trigger: Push to main, PR, weekly schedule Language matrix: ["javascript-typescript"]

3.2 Dependency Review (dependency-review.yml)

Tool: actions/dependency-review-action Trigger: Pull requests Gate: Blocks PRs with critical/high vulnerability dependencies

3.3 OpenSSF Scorecard (scorecards.yml)

Tool: OpenSSF Scorecard Trigger: Push to main, weekly schedule Purpose: Supply chain security assessment and OSSF best practices evaluation


๐Ÿš€ Stage 4: Release & Deployment

flowchart TD
    Trigger[๐Ÿท๏ธ Release Trigger] --> Build[๐Ÿ—๏ธ Vite Build]
    Build --> SBOM[๐Ÿ“„ Generate SBOM]
    SBOM --> Attestations[๐Ÿ” SLSA Attestations]
    Attestations --> TypeDoc[๐Ÿ“– Generate API Docs]
    TypeDoc --> DualDeploy{๐Ÿš€ Dual Deploy}

    DualDeploy --> S3[โ˜๏ธ AWS S3/CloudFront]
    DualDeploy --> GHP[๐Ÿ“„ GitHub Pages]

    S3 --> CFInvalidate[๐Ÿ”„ CloudFront Invalidation]
    GHP --> GHPCdn[๐ŸŒ GitHub CDN]

    CFInvalidate --> Live1[โœ… riksdagsmonitor.com]
    GHPCdn --> Live2[โœ… hack23.github.io/riksdagsmonitor]

    classDef trigger fill:#3498db,stroke:#2980b9,stroke-width:2px,color:white
    classDef build fill:#27ae60,stroke:#1e8449,stroke-width:1.5px,color:white
    classDef security fill:#e74c3c,stroke:#c0392b,stroke-width:1.5px,color:white
    classDef deploy fill:#FF9900,stroke:#232F3E,stroke-width:1.5px,color:white
    classDef complete fill:#16a085,stroke:#1abc9c,stroke-width:2px,color:white

    class Trigger trigger
    class Build,TypeDoc build
    class SBOM,Attestations security
    class DualDeploy,S3,GHP,CFInvalidate,GHPCdn deploy
    class Live1,Live2 complete

Release Pipeline Features:

  • ๐Ÿท๏ธ Tag-based Releases: Automatic releases on v* tag push
  • ๐Ÿ“‹ Manual Releases: Workflow dispatch with version input
  • ๐Ÿ”’ SLSA Attestations: Build provenance for supply chain security
  • ๐Ÿ“„ SBOM Generation: Software Bill of Materials
  • ๐Ÿ“– TypeDoc: API documentation generation
  • โ˜๏ธ Dual Deployment: AWS S3/CloudFront (primary) + GitHub Pages (DR)

S3 Sync Exclusions: .git/*, .github/*, node_modules/*, src/*, tests/*, cypress/*, builds/*, tsconfig*.json, *.config.js


๐Ÿ“Š Stage 5: CIA Data Integration

flowchart TD
    subgraph "โฐ Triggers"
        Nightly[๐Ÿ“… Nightly 03:30 UTC] --> Refresh[๐Ÿ“Š Update CIA CSV Data]
        Manual[๐Ÿ–ฑ Manual dispatch<br/><i>optional ref input</i>] --> Refresh
    end

    subgraph "๐Ÿ“Š CSV + Stats Refresh"
        Refresh --> TreeIdx[๐Ÿ“š Build basenameโ†’path index<br/>GitHub Tree API, recursive]
        TreeIdx --> Download[๐Ÿ“ฅ Download only already-tracked<br/>data/cia/** + cia-data/** CSVs]
        Download --> Stats[๐Ÿ“ˆ load-cia-stats.ts โ†’<br/>production-stats.json]
        Stats --> Inject[๐Ÿ–Š update-stats-from-cia.ts โ†’<br/>inject counts into 14ร— index*.html]
        Inject --> Diff{Any changes?}
        Diff -->|No| NoOp[โœ… No-op summary]
        Diff -->|Yes| AutoPR[๐Ÿ” Open single PR<br/>CSVs + stats + HTML]
    end

    classDef schedule fill:#ffecb3,stroke:#f57f17,stroke-width:1.5px,color:black
    classDef pipeline fill:#c8e6c9,stroke:#2e7d32,stroke-width:1.5px,color:black
    classDef decision fill:#f39c12,stroke:#e67e22,stroke-width:2px,color:black

    class Nightly,Manual schedule
    class Refresh,TreeIdx,Download,Stats,Inject,AutoPR,NoOp pipeline
    class Diff decision

Workflows:

  • ๐Ÿ“Š Update CIA CSV Data (update-cia-csv-data.yml): Nightly at 03:30 UTC and on manual dispatch.
    • Source of truth for what to refresh = the set of CSVs already tracked in this repository under data/cia/** and cia-data/**. The workflow never introduces new files.
    • Source of truth for where each CSV lives upstream = a basename โ†’ upstream-path index built once per run from the GitHub Tree API (/repos/Hack23/cia/git/trees/<ref>?recursive=1). This correctly resolves sub-folder CSVs (e.g. distinct_values/vote_data_party.csv, framework-validation/**, risk-rule-tests/**) โ€” the upstream layout is not flat. A <stem>_sample.csv alias is tried as a fallback for the handful of locally-renamed canonical files (view_riksdagen_committee_decisions.csv โ†’ upstream view_riksdagen_committee_decisions_sample.csv, etc.).
    • Stats refresh โ€” after the CSV step, the workflow runs npx tsx scripts/load-cia-stats.ts to regenerate cia-data/production-stats.json from upstream extraction_summary_report.csv, then npx tsx scripts/update-stats-from-cia.ts to inject the refreshed counts into all 14 index*.html language variants.
    • PR output โ€” a single automated pull request is opened via peter-evans/create-pull-request whenever CSV content, production-stats.json, or index*.html change. Byte-level cmp ensures commits are produced only on real diffs.
    • Skipped paths โ€” locally-curated files with no upstream equivalent are never overwritten: data/cia/ministry/sample_{influence,decision_impact,risk_levels,productivity}.csv and cia-data/election/{election_forecast,coalition_scenarios}.csv.

๐Ÿค– Stage 6: Agentic News Generation

Fourteen agentic workflows use the gh-aw (GitHub Agentic Workflows) framework to generate political-intelligence content following OSINT/INTOP editorial standards and the 23-artifact analysis baseline. The 13 analysis/article-generating workflows run on claude-opus-4.8 (strongest reasoning for the analysis pipeline), while the high-volume news-translate workflow stays on claude-sonnet-4.6 for translation-fan-out throughput.

flowchart TD
    subgraph "๐Ÿ“ฐ News Generation Pipeline"
        Trigger[โฐ Scheduled / Manual] --> PreAnalysis[๐Ÿ“Š Pre-Article Analysis]
        PreAnalysis --> Download[๐Ÿ“ฅ Download Riksdag Data]
        Download --> AIAnalysis[๐Ÿค– AI Analysis - Claude Opus 4.8]
        AIAnalysis --> Generate[๐Ÿ“ Generate Article]
        Generate --> QualityCheck[โœ… Quality Validation]
        QualityCheck --> Translate[๐ŸŒ Multi-Language Translation]
        Translate --> Deploy[๐Ÿ“ค Commit & Deploy]
    end

    subgraph "๐Ÿ“‹ 14 News Workflows"
        W1[๐Ÿ“Š Committee Reports]
        W2[๐Ÿ›๏ธ Propositions]
        W3[๐Ÿ“‹ Motions]
        W4[โ“ Interpellations]
        W5[๐Ÿ“ก Realtime Monitor]
        W6[๐ŸŒ… Evening Analysis]
        W7[๐Ÿ”ฎ Week Ahead]
        W8[๐Ÿ“… Month Ahead]
        W9[๐Ÿ“ Quarter Ahead]
        W10[๐Ÿ“† Year Ahead]
        W11[๐Ÿ—ณ๏ธ Election Cycle]
        W12[๐Ÿ“ฐ Weekly Review]
        W13[๐Ÿ“Š Monthly Review]
        W14[๐ŸŒ Translate]
    end

    classDef pipeline fill:#e1bee7,stroke:#6a1b9a,stroke-width:1.5px,color:black
    classDef workflow fill:#ce93d8,stroke:#6a1b9a,stroke-width:1px,color:black
    classDef ai fill:#9C27B0,stroke:#6a1b9a,stroke-width:2px,color:white

    class Trigger,PreAnalysis,Download,Generate,QualityCheck,Translate,Deploy pipeline
    class AIAnalysis ai
    class W1,W2,W3,W4,W5,W6,W7,W8,W9,W10,W11,W12,W13,W14 workflow

MCP Tools Available:

  • riksdag-regering-mcp (32 tools for Swedish political data)
  • @playwright/mcp (browser automation)
  • @modelcontextprotocol/server-filesystem
  • @modelcontextprotocol/server-memory

Compilation: Source .md โ†’ .lock.yml via compile-agentic-workflows.yml

Per-Workflow Data Download & Unique Analytics

Each agentic workflow downloads data from specific MCP tools and produces unique political intelligence that only that document type can provide:

graph TB
    subgraph "๐Ÿ“ฅ MCP Data Sources"
        BET["get_betankanden<br/><i>Committee reports</i>"]
        PROP["get_propositioner<br/><i>Government bills</i>"]
        MOT["get_motioner<br/><i>Opposition motions</i>"]
        INTERP["get_interpellationer<br/><i>Parliamentary questions</i>"]
        VOTE["search_voteringar<br/><i>Voting records</i>"]
        ANF["search_anforanden<br/><i>Debate speeches</i>"]
        DOK["search_dokument<br/><i>Document search</i>"]
        DOKFT["search_dokument_fulltext<br/><i>Full-text search</i>"]
        CAL["get_calendar_events<br/><i>Parliamentary calendar</i>"]
        SCB["SCB MCP<br/><i>Statistics Sweden</i>"]
        WB["World Bank MCP<br/><i>International data</i>"]
        IMF["IMF TypeScript client<br/><i>WEO + Fiscal Monitor + IFS<br/>pure-TS, not MCP</i>"]
    end

    subgraph "๐Ÿ“ฐ Agentic Workflows"
        WF_CR["๐Ÿ“‹ Committee Reports"]
        WF_PR["๐Ÿ“œ Propositions"]
        WF_MO["โœŠ Motions"]
        WF_IP["โ“ Interpellations"]
        WF_EV["๐ŸŒ™ Evening Analysis"]
        WF_RT["โšก Realtime Monitor"]
        WF_WR["๐Ÿ“… Weekly Review"]
        WF_WA["๐Ÿ”ฎ Week Ahead"]
    end

    BET --> WF_CR
    VOTE --> WF_CR
    ANF --> WF_CR
    PROP --> WF_CR
    SCB --> WF_CR
    WB --> WF_EV
    WB --> WF_WR
    IMF --> WF_EV
    IMF --> WF_WR
    IMF --> WF_WA
    IMF --> WF_CR
    PROP --> WF_PR
    DOKFT --> WF_PR
    ANF --> WF_PR
    MOT --> WF_MO
    DOKFT --> WF_MO
    ANF --> WF_MO
    INTERP --> WF_IP
    ANF --> WF_IP
    DOKFT --> WF_IP
    CAL --> WF_IP
    VOTE --> WF_EV
    ANF --> WF_EV
    BET --> WF_EV
    CAL --> WF_EV
    DOK --> WF_RT
    CAL --> WF_RT
    VOTE --> WF_RT
    ANF --> WF_RT
    BET --> WF_RT
    DOK --> WF_WR
    ANF --> WF_WR
    BET --> WF_WR
    PROP --> WF_WR
    MOT --> WF_WR
    VOTE --> WF_WR
    CAL --> WF_WA
    DOK --> WF_WA
    ANF --> WF_WA
    INTERP --> WF_WA

    style BET fill:#198754,color:#fff
    style PROP fill:#0d6efd,color:#fff
    style MOT fill:#fd7e14,color:#fff
    style INTERP fill:#dc3545,color:#fff
    style VOTE fill:#6f42c1,color:#fff
    style ANF fill:#d63384,color:#fff
    style DOK fill:#20c997,color:#000
    style DOKFT fill:#17a589,color:#fff
    style CAL fill:#0dcaf0,color:#000
    style SCB fill:#ffc107,color:#000
    style WB fill:#ff9800,color:#000
    style IMF fill:#00897b,color:#fff,stroke:#004d40,stroke-width:2px
    style WF_CR fill:#198754,color:#fff,stroke-width:2px
    style WF_PR fill:#0d6efd,color:#fff,stroke-width:2px
    style WF_MO fill:#fd7e14,color:#fff,stroke-width:2px
    style WF_IP fill:#dc3545,color:#fff,stroke-width:2px
    style WF_EV fill:#6f42c1,color:#fff,stroke-width:2px
    style WF_RT fill:#d63384,color:#fff,stroke-width:2px
    style WF_WR fill:#20c997,color:#000,stroke-width:2px
    style WF_WA fill:#0dcaf0,color:#000,stroke-width:2px
#WorkflowSchedulePrimary MCP DataUnique Analytics Produced
1Committee ReportsMonโ€“Fri 04:00 UTCget_betankanden, search_voteringar, search_anforanden, get_propositionerCommittee voting splits per party, reservation (dissent) analysis, committee-to-policy-domain mapping, SCB statistical enrichment per committee domain
2PropositionsMonโ€“Fri 05:00 UTCget_propositioner, search_dokument_fulltext, analyze_g0v_by_department, search_anforandenLegislative pipeline tracking (referral โ†’ committee โ†’ vote), government legislative ambition score, budget allocation impact analysis, policy domain cascading effects
3MotionsMonโ€“Fri 06:00 UTCget_motioner, search_dokument_fulltext, analyze_g0v_by_department, search_anforandenOpposition strategy analysis, motion clustering by theme, cross-party co-sponsorship detection, signalverdi (is this positioning or a real bid?)
4InterpellationsMonโ€“Fri 07:00 UTCget_interpellationer, search_anforanden, search_dokument_fulltext, get_calendar_eventsMinisterial accountability scoring (response rate/timeliness), evasion detection, question framing analysis, party oversight strategy mapping
5Realtime MonitorMonโ€“Fri 10:00+14:00, Weekends 12:00search_dokument, get_calendar_events, search_voteringar, search_anforanden, get_betankandenBreaking event detection, urgency classification, real-time political temperature spikes
6Evening AnalysisMonโ€“Fri 18:00, Sat 16:00search_voteringar, search_anforanden, get_betankanden, get_calendar_eventsDaily parliamentary pulse, party discipline metrics, coalition cohesion scoring, debate intensity index
7Weekly ReviewSat 09:00 UTCsearch_dokument, search_anforanden, get_betankanden, get_propositioner, get_motioner, search_voteringarWeek-over-week trend detection, cross-document-type pattern identification, legislative throughput metrics; IMF WEO / Fiscal Monitor projections enrich the weekly macroeconomic framing
8Week AheadFri 07:00 UTCget_calendar_events, search_dokument, search_anforanden, get_fragor, get_interpellationerProspective calendar analysis, scheduled debate preview, expected vote outcomes; IMF projections (T+5 horizon) are the primary source for forward-looking economic commentary
9Monthly Review28th 10:00 UTCsearch_dokument, search_anforanden, get_betankanden, get_propositioner, get_motioner, search_voteringarMonthly legislative throughput, party productivity rankings, government vs opposition scorecard; IMF IFS monthly series + WEO vintages used for fiscal/monetary context
10Month Ahead1st 08:00 UTCget_calendar_events, search_dokument, get_betankanden, get_propositioner, get_motionerStrategic political calendar, legislative pipeline forecast, major policy decision timeline; IMF WEO / Fiscal Monitor projection vintage (projectionVintage pinned per article) anchors medium-term outlook
11Article GeneratorManual onlyPer-type (configurable)Manual backfill/regeneration for any article type
12TranslateMonโ€“Fri 11:00+17:00, Weekends 14:00N/A (text processing)14-language translation quality with cultural adaptation

๐Ÿงฉ Stage 6.1: Agentic Workflow Structure & Prompt Imports

Every news-*.md source in .github/workflows/ is a gh-aw workflow โ€” a Markdown file whose YAML frontmatter compiles down, via gh aw compile, to a hardened GitHub Actions .lock.yml. A workflow is made up of three layers:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  news-<type>.md                                                         โ”‚
โ”‚  โ”œโ”€โ”€ Frontmatter (name, triggers, runtimes, network, tools, mcp-servers)โ”‚
โ”‚  โ”œโ”€โ”€ imports:                                                           โ”‚
โ”‚  โ”‚    โ”œโ”€โ”€ prompts/00-base-contract.md      โ† role, ethics, AI-FIRST     โ”‚
โ”‚  โ”‚    โ”œโ”€โ”€ prompts/01-bash-and-shell-safety.md                           โ”‚
โ”‚  โ”‚    โ”œโ”€โ”€ prompts/02-mcp-access.md         โ† MCP inventory + health     โ”‚
โ”‚  โ”‚    โ”œโ”€โ”€ prompts/03-data-download.md      โ† download pipeline          โ”‚
โ”‚  โ”‚    โ”œโ”€โ”€ prompts/04-analysis-pipeline.md  โ† 23 artifacts (4 families), Pass 1+2 โ”‚
โ”‚  โ”‚    โ”œโ”€โ”€ prompts/05-analysis-gate.md      โ† BLOCKING artifact gate     โ”‚
โ”‚  โ”‚    โ”œโ”€โ”€ prompts/06-article-generation.md โ† sections, banned patterns  โ”‚
โ”‚  โ”‚    โ””โ”€โ”€ prompts/07-commit-and-pr.md      โ† stage โ†’ commit โ†’ PR        โ”‚
โ”‚  โ”œโ”€โ”€ (Tier-C only) imports: prompts/ext/tier-c-aggregation.md โ† depth multipliers โ”‚
โ”‚  โ””โ”€โ”€ Body = per-type instructions (e.g. "generate propositions article")โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                โ”‚
                                โ”‚  gh aw compile
                                โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  news-<type>.lock.yml    (the only file GitHub Actions executes)        โ”‚
โ”‚  โ”œโ”€โ”€ SHA-pinned actions (100%)                                          โ”‚
โ”‚  โ”œโ”€โ”€ step-security/harden-runner with egress audit                      โ”‚
โ”‚  โ”œโ”€โ”€ Squid proxy + iptables firewall over network.allowed:              โ”‚
โ”‚  โ”œโ”€โ”€ Five-layer safe-outputs validator                                  โ”‚
โ”‚  โ””โ”€โ”€ MCP servers wired: riksdag-regering, scb, world-bank               โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Import order is a contract

The import order is not arbitrary โ€” each module builds on the previous one, and .github/prompts/05-analysis-gate.md is a single blocking gate that refuses to let the agent draft a single article sentence until all required artifacts are on disk in analysis/daily/$ARTICLE_DATE/$SUBFOLDER/ for both Pass 1 and Pass 2. The baseline is 23 artifacts; year-ahead requires 24 (23 + pestle-analysis.md via LH-4); election-cycle requires 28 (23 + 5 blocking supplementary via LH-4 + LH-5: pestle-analysis.md, cycle-trajectory.md, wildcards-blackswans.md, quantitative-swot.md, political-stride-assessment.md).

Import #ModuleResponsibilityWhat fails fast if missing
100-base-contract.mdRole, editorial ethics, GDPR, ISMS, AI-FIRST 2-pass minimumEthics drift, privacy leaks, shallow output
201-bash-and-shell-safety.mdUTF-8 shell patterns, no eval, no shell-expansion exploitsCommand injection, encoding corruption
302-mcp-access.mdMCP server inventory + health probeWrong tool called, missing data source
403-data-download.mdDownload manifest, source attribution, cachingUnsourced claims
504-analysis-pipeline.md23 required artifacts (Family Aโ€“D), methodology โ†’ template bindings, Pass 1 + Pass 2Shallow analysis, template mismatch
605-analysis-gate.mdBlocks article generation until artifacts are completeAny article written before gate passes โ†’ workflow failure
706-article-generation.mdArticle sections, banned hype patterns, visualisation, translationsBoilerplate content, missing charts
807-commit-and-pr.mdStage โ†’ commit โ†’ exactly one create_pull_request callOrphan commits, duplicate PRs
9 (Tier-C only)ext/tier-c-aggregation.mdDepth multipliers, cross-type synthesis, higher article floor (same 23 artifacts)Aggregation without base artifacts

Dependency graph

flowchart TB
  subgraph WF["news-&lt;type&gt;.md (workflow source)"]
    FM[Frontmatter<br/>triggers ยท runtimes ยท network ยท mcp-servers]
    BODY[Body<br/>per-type analysis instructions]
  end

  subgraph PROMPTS[".github/prompts/ (shared bounded contexts)"]
    P00[00-base-contract]
    P01[01-bash-and-shell-safety]
    P02[02-mcp-access]
    P03[03-data-download]
    P04[04-analysis-pipeline]
    P05[05-analysis-gate โš ๏ธ blocking]
    P06[06-article-generation]
    P07[07-commit-and-pr]
    PEXT[ext/tier-c-aggregation]
  end

  subgraph METH["analysis/methodologies/"]
    M1[ai-driven-analysis-guide]
    M2[per-document-methodology]
    M3[political-risk-methodology]
    M4[political-swot-framework]
    M5[political-threat-framework]
    M6[synthesis-methodology]
  end

  subgraph TPL["analysis/templates/ (23 output templates)"]
    T1[per-file-political-intelligence]
    T2[risk-assessment]
    T3[swot-analysis]
    T4[threat-analysis]
    T5[stakeholder-impact]
    T6[scenario-analysis]
    T7[significance-scoring]
    T8[executive-brief]
    T9[cross-reference-map]
    T10[synthesis-summary]
    T11[devils-advocate]
    T12[methodology-reflection]
    T13[โ€ฆ + 11 more]
  end

  FM --> P00 --> P01 --> P02 --> P03 --> P04 --> P05 --> P06 --> P07
  P04 -.binds.-> METH
  P04 -.binds.-> TPL
  P05 -.verifies.-> TPL
  BODY --> PEXT
  PEXT -. Tier-C only .-> P05

  style P05 fill:#dc3545,color:#fff,stroke:#b02a37,stroke-width:3px
  style PEXT fill:#fd7e14,color:#fff,stroke:#ca6510

Single-type vs. Tier-C artifact contract

All workflows produce the same 23 always-on artifacts (Family A 9 + Family B 2 + Family C 5 + Family D 7) defined in prompts/04-analysis-pipeline.md. The counts below are baseline blocking artifacts from the main gate checks and long-horizon checks (LH-4, LH-5). In addition, the gate's supplementary checks (S1โ€“S7 in 05-analysis-gate.md) can block runs depending on tier and article type:

  • comprehensive tier and aggregation types (weekly-review, monthly-review): analysis-index.md, reference-analysis-quality.md, mcp-reliability-audit.md, workflow-audit.md become blocking; aggregation types also require cross-session-intelligence.md and session-baseline.md
  • Multi-run (โ‰ฅ 2 production runs of the same article type): cross-run-diff.md becomes blocking

Long-horizon gates (LH-4, LH-5) additionally require analytical supplementary artifacts that are normally optional but become blocking for specific workflows:

  • Year-ahead (LH-4): pestle-analysis.md โ€” total 24 baseline blocking artifacts
  • Election-cycle (LH-4 + LH-5): pestle-analysis.md + cycle-trajectory.md + wildcards-blackswans.md + quantitative-swot.md + political-stride-assessment.md โ€” total 28 baseline blocking artifacts
ContractApplies toBaseline blockingDepthSource
Single-typenews-propositions, news-motions, news-committee-reports, news-interpellations23standard/deepprompts/05-analysis-gate.md
Tier-C aggregationnews-evening-analysis, news-realtime-monitor, news-week-ahead, news-month-ahead, news-weekly-review, news-monthly-review, news-quarter-ahead23 (+ S1โ€“S7 per tier/type)ร— 1.0โ€“1.7prompts/ext/tier-c-aggregation.md
Tier-C + year-aheadnews-year-ahead24 (23 + pestle-analysis.md via LH-4; + S1โ€“S7 per tier)ร— 2.0prompts/ext/tier-c-aggregation.md + LH-4
Tier-C + election-cyclenews-election-cycle28 (23 + 5 via LH-4 + LH-5; + S1โ€“S7 per tier)ร— 2.5prompts/ext/tier-c-aggregation.md + LH-4 + LH-5
Translation (N/A)news-translateN/A (catch-up only โ€” primary translation now happens inside each per-type run)โ€”Direct text pipeline

All artifacts are written under analysis/daily/$ARTICLE_DATE/$SUBFOLDER/ โ€” see analysis/README.md for the on-disk layout and analysis/templates/README.md for the 23 canonical templates.

MCP server wiring (identical across all 14 agentic workflows)

mcp-servers:
  riksdag-regering:                           # HTTP (hosted)
    url: https://riksdag-regering-ai.onrender.com/mcp
    allowed: ["*"]
  scb:                                         # Container (per-run)
    container: "node:26-alpine"
    entrypoint: "npx"
    entrypointArgs: ["-y", "@jarib/pxweb-mcp@2.0.0",
                     "--url", "https://api.scb.se/OV0104/v2beta"]
    allowed: ["*"]
  world-bank:                                  # Container (per-run)
    container: "node:26-alpine"
    entrypoint: "npx"
    entrypointArgs: ["-y", "worldbank-mcp@1.0.1"]
    allowed: ["*"]

In addition, every workflow activates the gh-aw-provided github (all toolsets), agentic-workflows, bash, playwright, and repo-memory tools. IMF ingestion is not an MCP server โ€” it is pulled by scripts/imf-client.ts (pure-TS Datamapper JSON + SDMX 3.0 client), fully covered by the npm SBOM, so the total MCP server count remains 8 (3 shared here + 5 repo-level in .github/copilot-mcp.json).

Network egress allow-list (applies to every agentic workflow)

network:
  allowed:
    - node                              # npm registry ecosystem
    - github                            # GitHub API
    - defaults                          # Curated dev domains
    - riksdag-regering-ai.onrender.com  # Riksdag MCP
    - api.scb.se                        # Statistics Sweden
    - api.worldbank.org                 # World Bank
    - api.imf.org                       # IMF (for imf-client.ts)
    - data.riksdagen.se                 # Riksdag open data
    - riksdagen.se / www.riksdagen.se   # Riksdag website
    - regeringen.se / www.regeringen.se # Government website
    - hack23.com / www.hack23.com       # Hack23 platform
    - riksdagsmonitor.com               # This platform
    - raw.githubusercontent.com         # Raw GitHub content
    - hack23.github.io                  # GitHub Pages DR

Any outbound connection not matching this allow-list is dropped at the Squid proxy / iptables layer.

Compilation lifecycle

  1. Author edits news-<type>.md.
  2. PR triggers compile-agentic-workflows.yml.
  3. That workflow runs gh aw compile to regenerate the sibling .lock.yml.
  4. Reviewer inspects the .md source of truth and confirms the .lock.yml diff.
  5. Once merged, the next cron/dispatch runs the .lock.yml under the hardened runner.

Rule: never edit a .lock.yml by hand โ€” the next compilation pass will overwrite it. All review feedback must target the .md source and the prompt modules it imports.


๐Ÿ”ฎ Stage 6.2: Long-Horizon Forward-Look Pipelines (quarter / year / election-cycle)

The three long-horizon workflows extend the forward-look family beyond week-ahead and month-ahead. They share the Tier-C aggregation contract but apply progressively higher depth multipliers and require additional prompt modules (ext/long-horizon-forecasting.md; ext/cycle-rollover.md for election-cycle only). Full horizon metadata is defined in analysis/article-types.json; editorial parameters are documented in Article-Generation.md ยง Forward-Look Horizons.

๐Ÿ“ 6.2.1 News Quarter Ahead (news-quarter-ahead)

Schedule: 0 9 1,15 * * (1st + 15th of month, 09:00 UTC) Horizon: 90 days | Depth multiplier: ร— 1.7 | Word floor: 2 000 | Timeout: 45 min

flowchart TD
    subgraph Imports["Prompt-module imports"]
        P00["00-base-contract"]
        P01["01-bash-and-shell-safety"]
        P02["02-mcp-access"]
        P03["03-data-download"]
        P04["04-analysis-pipeline"]
        P05["05-analysis-gate โ›”"]
        P06["06-article-generation"]
        P07["07-commit-and-pr"]
        EXT1["ext/tier-c-aggregation"]
        EXT2["ext/long-horizon-forecasting"]
    end

    subgraph MCP["MCP-server access"]
        RR["riksdag-regering<br/>(Riksdag calendar, committee schedules)"]
        SCB["SCB PxWeb<br/>(quarterly NA, Riksbank rates)"]
        WB["world-bank<br/>(governance residue)"]
        IMF["IMF WEO/FM via bash<br/>(macro projections)"]
    end

    subgraph Pipeline["Pipeline stages"]
        A1["๐Ÿ“ฅ Data download<br/>(committee schedule, prop tabling)"]
        A2["๐Ÿ”ฌ Analysis (23 artifacts)<br/>Tier-C ร— 1.7 depth"]
        A3["โ›” Analysis gate<br/>(blocks until 23 artifacts)"]
        A4["๐Ÿ“ Article generation<br/>(โ‰ฅ 2000 words)"]
        A5["๐Ÿ”’ Safe-outputs envelope<br/>(sanitise โ†’ validate โ†’ PR)"]
    end

    Imports --> Pipeline
    MCP --> A1
    A1 --> A2 --> A3 --> A4 --> A5
sequenceDiagram
    participant Cron as โฐ Cron (1st/15th 09:00)
    participant Runner as ๐Ÿ–ฅ๏ธ gh-aw Runner
    participant MCP as ๐Ÿ“ก MCP Servers
    participant Gate as โ›” Analysis Gate
    participant SO as ๐Ÿ”’ Safe-Outputs

    Cron->>Runner: trigger news-quarter-ahead
    Runner->>MCP: fetch committee schedule + propositions calendar (90d)
    MCP-->>Runner: structured data
    Runner->>Runner: analysis pipeline (23 artifacts, ร— 1.7)
    Runner->>Gate: verify 23 artifacts present
    Gate-->>Runner: PASS
    Runner->>Runner: render article (โ‰ฅ 2000 words EN+SV)
    Runner->>SO: submit PR via safe-outputs
    SO-->>Runner: PR created (human review)
    Note over Runner,SO: Hard deadline: 45 min timeout

๐Ÿ“† 6.2.2 News Year Ahead (news-year-ahead)

Schedule: 0 9 5 1,7 * (5th of January + 5th of July, 09:00 UTC) Horizon: 365 days | Depth multiplier: ร— 2.0 | Word floor: 2 500 | Timeout: 45 min

flowchart TD
    subgraph Imports["Prompt-module imports"]
        P00["00-base-contract"]
        P01["01-bash-and-shell-safety"]
        P02["02-mcp-access"]
        P03["03-data-download"]
        P04["04-analysis-pipeline"]
        P05["05-analysis-gate โ›”"]
        P06["06-article-generation"]
        P07["07-commit-and-pr"]
        EXT1["ext/tier-c-aggregation"]
        EXT2["ext/long-horizon-forecasting"]
    end

    subgraph MCP["MCP-server access"]
        RR["riksdag-regering<br/>(Riksmรถte calendar, VPs + BPs)"]
        SCB["SCB PxWeb<br/>(annual NA, demographic)"]
        WB["world-bank<br/>(WGI governance)"]
        IMF["IMF WEO Apr/Oct vintage<br/>(GDP, growth, fiscal)"]
    end

    subgraph Pipeline["Pipeline stages"]
        A1["๐Ÿ“ฅ Data download<br/>(budget rhythm: BP autumn + VP spring)"]
        A2["๐Ÿ”ฌ Analysis (23 + 1 gate-blocking + 2 mandated)<br/>Tier-C ร— 2.0 depth + pestle-analysis.md (LH-4)<br/>+ wildcards-blackswans.md + quantitative-swot.md"]
        A3["โ›” Analysis gate<br/>(blocks until 24: 23 baseline + pestle-analysis.md)<br/>wildcards + SWOT mandated by registry, not gate-blocking"]
        A4["๐Ÿ“ Article generation<br/>(โ‰ฅ 2500 words, wildcards-blackswans)"]
        A5["๐Ÿ”’ Safe-outputs envelope<br/>(sanitise โ†’ validate โ†’ PR)"]
    end

    Imports --> Pipeline
    MCP --> A1
    A1 --> A2 --> A3 --> A4 --> A5
sequenceDiagram
    participant Cron as โฐ Cron (5 Jan/Jul 09:00)
    participant Runner as ๐Ÿ–ฅ๏ธ gh-aw Runner
    participant MCP as ๐Ÿ“ก MCP Servers
    participant IMF as ๐Ÿ’น IMF WEO/FM
    participant Gate as โ›” Analysis Gate
    participant SO as ๐Ÿ”’ Safe-Outputs

    Cron->>Runner: trigger news-year-ahead
    Runner->>MCP: fetch Riksmรถte + budget calendar (365d)
    Runner->>IMF: fetch WEO Apr/Oct vintage projections
    MCP-->>Runner: parliamentary data
    IMF-->>Runner: macro projections (GDP, inflation, fiscal)
    Runner->>Runner: analysis pipeline (24 gate-blocking + 2 mandated: pestle + wildcards + SWOT, ร— 2.0)
    Runner->>Runner: LH-4: pestle-analysis.md blocking; wildcards + SWOT mandated by registry
    Runner->>Gate: verify 24 gate-blocking artifacts (23 baseline + pestle-analysis.md via LH-4)
    Gate-->>Runner: PASS
    Runner->>Runner: render article (โ‰ฅ 2500 words EN+SV)
    Runner->>SO: submit PR via safe-outputs
    SO-->>Runner: PR created (human review)
    Note over Runner,SO: Hard deadline: 45 min timeout

๐Ÿ—ณ๏ธ 6.2.3 News Election Cycle (news-election-cycle)

Schedule: workflow_dispatch only (cron 0 9 13 3,9 * declared but disabled until runtime measured) Horizon: 1 460 days (4-year mandate) | Depth multiplier: ร— 2.5 | Word floor: 3 500 | Timeout: 45 min Extra imports: ext/cycle-rollover.md (active ยฑ30 days of election anchor 2026-09-13)

flowchart TD
    subgraph Imports["Prompt-module imports (11 modules)"]
        P00["00-base-contract"]
        P01["01-bash-and-shell-safety"]
        P02["02-mcp-access"]
        P03["03-data-download"]
        P04["04-analysis-pipeline"]
        P05["05-analysis-gate โ›”"]
        P06["06-article-generation"]
        P07["07-commit-and-pr"]
        EXT1["ext/tier-c-aggregation"]
        EXT2["ext/long-horizon-forecasting"]
        EXT3["ext/cycle-rollover"]
    end

    subgraph MCP["MCP-server access"]
        RR["riksdag-regering<br/>(full mandate voting record)"]
        SCB["SCB PxWeb<br/>(demographic, economic)"]
        WB["world-bank<br/>(WGI governance 4-year)"]
        IMF["IMF WEO multi-year<br/>(T+5 projections)"]
    end

    subgraph Pipeline["Pipeline stages"]
        A1["๐Ÿ“ฅ Data download<br/>(Tidรถ scorecard + next-cycle coalition)"]
        A2["๐Ÿ”ฌ Analysis (23 + 5 artifacts)<br/>Tier-C ร— 2.5 depth + 5 blocking supplementary"]
        A3["โ›” Analysis gate<br/>(blocks until 28: 23 baseline + pestle + cycle-trajectory + wildcards + SWOT + STRIDE)"]
        A4["๐Ÿ“ Article generation<br/>(โ‰ฅ 3500 words, STRIDE assessment)"]
        A5["๐Ÿ”’ Safe-outputs envelope<br/>(sanitise โ†’ validate โ†’ PR)"]
    end

    Imports --> Pipeline
    MCP --> A1
    A1 --> A2 --> A3 --> A4 --> A5
sequenceDiagram
    participant Op as ๐Ÿ‘ค Operator (dispatch)
    participant Runner as ๐Ÿ–ฅ๏ธ gh-aw Runner
    participant MCP as ๐Ÿ“ก MCP Servers
    participant IMF as ๐Ÿ’น IMF WEO T+5
    participant Gate as โ›” Analysis Gate
    participant SO as ๐Ÿ”’ Safe-Outputs

    Op->>Runner: workflow_dispatch (cycle_anchor=both)
    Runner->>MCP: fetch full mandate voting record + coalition data
    Runner->>IMF: fetch multi-year WEO projections
    MCP-->>Runner: 4-year parliamentary data
    IMF-->>Runner: T+5 macro projections
    Runner->>Runner: analysis pipeline (28 artifacts: 23 + 5 blocking supplementary, ร— 2.5)
    Runner->>Runner: LH-4: pestle-analysis.md; LH-5: cycle-trajectory + wildcards + SWOT + STRIDE
    Runner->>Gate: verify 28 artifacts (23 baseline + pestle + cycle-trajectory + wildcards-blackswans + quantitative-swot + political-stride-assessment)
    Gate-->>Runner: PASS
    Runner->>Runner: render article (โ‰ฅ 3500 words EN+SV)
    Runner->>SO: submit PR via safe-outputs
    SO-->>Runner: PR created (human review)
    Note over Runner,SO: Hard deadline: 45 min timeout

๐Ÿ“Š Long-Horizon ISMS Control Mapping

The three long-horizon workflows touch additional ISMS controls beyond the standard agentic security model:

ControlStandardHow Applied
A.5.1 (Policies for information security)ISO 27001:2022Long-horizon forecasts classified PUBLIC; no PII processed; GDPR DPIA short-circuit
A.5.30 (ICT readiness for business continuity)ISO 27001:2022Graceful fallback if MCP/IMF unavailable โ€” uses cached vintage with annotation
A.8.8 (Management of technical vulnerabilities)ISO 27001:2022IMF/SCB egress pins in Squid allowlist; .meta.json provenance sidecars for fetched data
A.8.28 (Secure coding)ISO 27001:2022Prompt injection detection in safe-outputs layer; no user input reaches shell
A.8.30 (Outsourced development)ISO 27001:2022gh-aw compiler generates hardened .lock.yml; human review mandatory
GV.SC (Supply chain risk management)NIST CSF 2.0MCP server versions pinned; egress firewall restricts external calls
PR.DS (Data security)NIST CSF 2.0Analysis artifacts written to branch-protected path; no secrets in output
DE.CM (Continuous monitoring)NIST CSF 2.0Workflow timeout enforcement (45 min); GitHub Actions run-duration visible in dashboard
RS.AN (Incident analysis)NIST CSF 2.0Failed analysis-gate logs structured error messages; workflow conclusion captured in Actions history
#4 (Secure configuration)CIS Controls v8.1Harden-runner enforced; read-only permissions; concurrency guards
#16 (Application software security)CIS Controls v8.1Five-layer safe-outputs validator; AI output sanitisation

๐Ÿ“ˆ Long-Horizon KPIs

KPIDefinitionTargetMeasurement
Legislative calendar coverage (quarter)% of committee schedule + chamber sittings + proposition tabling deadlines forecast for the 90-day windowโ‰ฅ 85%Cross-reference generated quarter-ahead against data.riksdagen.se calendar API
Legislative calendar coverage (year)% of Riksmรถte + budget rhythm events forecast for 365-day windowโ‰ฅ 70%Compare year-ahead output against known BP/VP/session dates
Legislative calendar coverage (cycle)% of mandate-level milestones (elections, coalition formations, government reshuffles) forecastโ‰ฅ 60%Retrospective scoring after events occur
PIR roll-forward continuity% of Priority Intelligence Requirements from prior horizon article with explicit obsolescence date or roll-forward in next articleโ‰ฅ 90%Automated diff of PIR sections between consecutive articles
Vintage discipline rate% of IMF WEO/FM citations that include projection-year stamp (e.g. "WEO Apr-2026 est.")100%Regex validation in safe-outputs layer
Analysis gate pass rate% of workflow runs that pass the analysis gate on first attemptโ‰ฅ 80%GitHub Actions run outcome data
Safe-outputs rejection rate% of PRs rejected by safe-outputs validator< 5%PR merge/close statistics

๐Ÿ“ก Stage 7: Monitoring & Infrastructure

flowchart LR
    subgraph "๐Ÿ“ก Availability Monitoring"
        Cron[โฐ Every 15 min] --> Check14[๐ŸŒ Check 14 Languages]
        Check14 --> Headers[๐Ÿ”’ Security Headers]
        Headers --> Result{Available?}
        Result -->|No| CreateIssue[๐Ÿšจ Create Issue]
        Result -->|Yes| CloseIssue[โœ… Close Issue]
    end

    subgraph "๐Ÿ”† Performance Monitoring"
        Weekly[โฐ Weekly] --> LH[๐Ÿ”† Lighthouse CI]
        LH --> Perf[โšก Performance]
        LH --> A11y[โ™ฟ Accessibility]
        LH --> SEO[๐Ÿ” SEO]
        LH --> BP[โœ… Best Practices]
    end

    classDef schedule fill:#ffecb3,stroke:#f57f17,stroke-width:1.5px,color:black
    classDef check fill:#c8e6c9,stroke:#2e7d32,stroke-width:1.5px,color:black
    classDef alert fill:#ffccbc,stroke:#bf360c,stroke-width:1.5px,color:black
    classDef success fill:#a5d6a7,stroke:#1b5e20,stroke-width:1.5px,color:black

    class Cron,Weekly schedule
    class Check14,Headers,LH,Perf,A11y,SEO,BP check
    class CreateIssue alert
    class CloseIssue,Result success

Uptime Monitor (uptime-monitor.yml):

  • Every 15 minutes โ€” checks all 14 language homepages
  • Validates security headers (HSTS, CSP, X-Frame-Options)
  • Auto-creates/closes GitHub issues on outage/recovery

Lighthouse CI (lighthouse-ci.yml):

  • Weekly + push/PR to main
  • Targets: LCP < 2.5s, CLS < 0.1, Accessibility โ‰ฅ 90

๐Ÿ”ง Complete Workflow Inventory (54 Files โ€” 26 standard .yml + 14 agentic .md + 14 compiled .lock.yml)

Verification: ls .github/workflows/ yields 54 workflow files (55 entries including the directory README.md). This matches 26 standard workflow files + 14 agentic Markdown sources + 14 corresponding compiled lock files. Badges and PR checks are driven by the 26 standard .yml plus the 14 compiled .lock.yml (GitHub Actions only executes the compiled artifacts).

๐Ÿ” Security & Compliance (6 workflows)

#WorkflowFileTriggerISMS Controls
1.1๐Ÿ” CodeQL Analysiscodeql.ymlPush, PR, WeeklyA.8.8, PR.DS-6, CIS 16.6
1.2๐Ÿ“ฆ Dependency Reviewdependency-review.ymlPull requestsA.8.8, PR.DS-6, CIS 16.6
1.3โญ OpenSSF Scorecardscorecards.ymlPush to main, WeeklyA.5.36, DE.CM-6, CIS 16.2
1.4๐Ÿท๏ธ Setup Labelssetup-labels.ymlManual dispatchA.5.37, PR.IP-1
1.5๐Ÿท๏ธ PR Labelerlabeler.ymlPull requestsA.5.37, PR.IP-1
1.6๐Ÿ•ท๏ธ ZAP DAST Scanzap-scan.ymlWeekly schedule, manual dispatchA.8.29, DE.CM-8, CIS 18

๐Ÿงช Testing & Validation (10 workflows)

#WorkflowFileTriggerCoverage
2.1๐Ÿงช TypeScript & JS Testingjavascript-testing.ymlPush/PR (TS/JS/HTML)TSC + Vitest + Cypress
2.2๐Ÿ“– TypeDoc Validationjsdoc-validation.ymlManual dispatchTypeDoc generation + coverage
2.3โœ… Quality Checksquality-checks.ymlPush/PR to mainESLint + HTMLHint + linkinator
2.4๐Ÿงน Knip Dead Code Checkknip.ymlPush/PR to mainUnused files, deps, binaries, duplicate exports (blocking); unused exports/types (informational)
2.5๐ŸŒ Translation Validationtranslation-validation.ymlPush/PR (HTML)14-language + RTL + hreflang
2.6๐Ÿ–ฅ๏ธ Test Dashboardtest-dashboard.ymlPush/PR (src/browser)Dashboard Cypress E2E
2.7๐Ÿ  Test Homepagetest-homepage.ymlPush/PR (src/browser)Homepage Cypress E2E
2.8๐Ÿ“ฐ Test Newstest-news.ymlPush/PR (news)News pages Cypress E2E
2.9๐ŸŒ Executive Brief Translation Checksexec-brief-translation-checks.ymlPull requestsStructural-parity + file-ownership merge gate for the executive-brief translation pipeline
2.10๐Ÿ”ค Test Article Headerstest-article-headers.ymlManual dispatchAudits rendered <head> metadata (title/description/keywords + OpenGraph/Twitter) via the shared computeArticleHeadMetadata composer

๐Ÿ“Š CIA Data Pipeline (1 workflow)

#WorkflowFileTriggerPurpose
3.1๐Ÿ“Š Update CIA CSV Dataupdate-cia-csv-data.ymlNightly 03:30 UTC, manual dispatchRefresh every already-tracked data/cia/** and cia-data/** CSV from upstream Hack23/cia sample-data (recursive basenameโ†’path index handles sub-folders), refresh production-stats.json, inject counts into all 14 index*.html; auto-PR on changes

๐Ÿš€ Release & Deployment (3 workflows)

#WorkflowFileTriggerTargets
4.1๐Ÿš€ Release with Attestationsrelease.ymlPush tags (v*), manualSLSA + dual deploy
4.2โ˜๏ธ Deploy to S3deploy-s3.ymlPush to mainAWS S3/CloudFront
4.3๐Ÿ”† Lighthouse CI`lighthouse-ci.yml$\text{Push}/\text{PR}, \text{weekly}\text{Performance} \text{audit}

๐Ÿค– \text{Agentic} \text{Workflows} (14 \text{workflows} \times 2 \text{files} \text{each} = 28 \text{files})

\text{Each} \text{agentic} \text{workflow} \text{is} \text{authored} \text{as} \text{a} \text{Markdown} \text{source} ($.md) and **compiled** to a hardened GitHub Actions workflow (.lock.yml) via compile-agentic-workflows.yml. Only the .lock.ymlexecutes on the runner; the.md` is the source of truth, reviewed in PRs. Both files are SHA-pinned, run behind the Squid/iptables egress firewall, and route all write-side effects through the five-layer safe-outputs validator (sanitisation โ†’ schema-validate โ†’ policy-check โ†’ human-review โ†’ merge).

Pipeline model: each per-type news workflow runs analysis โ†’ aggregate โ†’ translate (13 non-English languages) โ†’ render (--lang all, 14 HTML files) โ†’ PR in a single agentic run. The legacy two-step news-article-generator (scaffold + later fill) workflow has been removed; articles are now derived directly from analysis/daily/$DATE/$SUB/ artifacts via scripts/aggregate-analysis.ts โ†’ per-language Markdown translation โ†’ scripts/render-articles.ts --lang all. The dedicated news-translate workflow is now a quality / catch-up workflow only โ€” it re-validates upstream translations and back-fills any language that an upstream run could not finish under its 60-min budget.

#WorkflowSourceLockPurpose
5.1๐ŸŒ… News Evening Analysisnews-evening-analysis.mdnews-evening-analysis.lock.ymlTier-C aggregation: end-of-day political analysis
5.2๐Ÿ“ก News Realtime Monitornews-realtime-monitor.mdnews-realtime-monitor.lock.ymlTier-C aggregation: real-time political monitoring
5.3๐Ÿ“‹ News Motionsnews-motions.mdnews-motions.lock.ymlSingle-type: motion tracking and reporting
5.4๐Ÿ“Š News Committee Reportsnews-committee-reports.mdnews-committee-reports.lock.ymlSingle-type: committee report coverage
5.5๐Ÿ“ฐ News Weekly Reviewnews-weekly-review.mdnews-weekly-review.lock.ymlTier-C aggregation: weekly political summary
5.6๐Ÿ“† News Monthly Reviewnews-monthly-review.mdnews-monthly-review.lock.ymlTier-C aggregation: monthly political review
5.7๐Ÿ”ฎ News Week Aheadnews-week-ahead.mdnews-week-ahead.lock.ymlTier-C aggregation: upcoming week preview
5.8๐Ÿ“… News Month Aheadnews-month-ahead.mdnews-month-ahead.lock.ymlTier-C aggregation: upcoming month preview
5.9๐Ÿ›๏ธ News Propositionsnews-propositions.mdnews-propositions.lock.ymlSingle-type: government proposition coverage
5.10โ“ News Interpellationsnews-interpellations.mdnews-interpellations.lock.ymlSingle-type: interpellation debate tracking
5.11๐ŸŒ News Translate (catch-up)news-translate.mdnews-translate.lock.ymlQuality / catch-up only: re-validates upstream translations, refines drift, back-fills languages an upstream run could not finish
5.12๐Ÿ“ News Quarter Aheadnews-quarter-ahead.mdnews-quarter-ahead.lock.ymlTier-C aggregation ร— 1.7: 90-day parliamentary-season + Riksbank/SCB calendar
5.13๐Ÿ“† News Year Aheadnews-year-ahead.mdnews-year-ahead.lock.ymlTier-C aggregation ร— 2.0: 365-day annual outlook anchored in IMF WEO Apr/Oct vintage
5.14๐Ÿ—ณ๏ธ News Election Cyclenews-election-cycle.mdnews-election-cycle.lock.ymlTier-C aggregation ร— 2.5: full 4-year mandate; dispatch-only until runtime measured

๐Ÿ› ๏ธ Automation & Tooling (4 workflows)

#WorkflowFileTriggerPurpose
6.1๐Ÿ”ง Compile Agentic Workflowscompile-agentic-workflows.ymlPush/PR touching news-*.md, manualCompile .md sources โ†’ .lock.yml via gh-aw compiler; enforces firewall + safe-outputs + SHA-pinning policy
6.2๐Ÿงน Agentics Maintenanceagentics-maintenance.ymlScheduled + manualScheduled hygiene of agentic environment: stale branch cleanup, secret rotation hooks, runtime-cache eviction, agent-config validation
6.3โ™ป๏ธ Regenerate Articlesregenerate-articles.ymlManual dispatchDeterministic (no-AI) rebuild of every article.md (via aggregate-analysis) and every news/*.html page (via render-articles, all 14 languages) from the current analysis/daily/ tree; commits directly to main
6.4๐Ÿค News Host-side PAT PR Fallbacknews-pat-pr-fallback.ymlworkflow_run after each news-* workflowSingle host-side recovery path for all 14 news workflows: replays the sandbox commit-handoff bundle under a host PAT to open/refresh the PR when the in-sandbox safe-outputs push could not deliver

๐Ÿ“ก Monitoring & Infrastructure (2 workflows)

#WorkflowFileTriggerPurpose
7.1๐Ÿ“ก Uptime Monitoruptime-monitor.ymlEvery 15 minutesSite availability checks
7.2๐Ÿค– Copilot Setup Stepscopilot-setup-steps.ymlPush, manualAgent environment setup

๐Ÿงฉ Extracted Script Modules (scripts/agentic/)

The inline bash validation logic embedded in .github/prompts/05-analysis-gate.md has been extracted into strictly-typed TypeScript modules under scripts/agentic/. This bounded context provides:

ModuleResponsibility
scripts/agentic/artifact-inventory.tsTyped definitions for all 23 required artifacts (Families Aโ€“D), stub placeholders, evidence patterns, agency lists, dok_id patterns
scripts/agentic/analysis-gate.tsGate validation checks 1โ€“9b: artifact existence, per-document coverage, stub detection, Mermaid validation, Family C/D structure, PIR sidecar, Statskontoret evidence
scripts/agentic/index.tsBarrel export โ€” single public surface for downstream consumers

Key types exported:

  • ArtifactFamily โ€” 'A' | 'B' | 'C' | 'D' | 'E'
  • ArtifactDefinition โ€” filename, family, description, gate metadata
  • GateCheckResult โ€” per-check pass/fail with message and artifact reference
  • GateValidationResult โ€” aggregate result with failure count

Design principles:

  • Zero any types โ€” explicit interfaces for all data structures
  • Gate module factored for readability (single-responsibility check functions)
  • Co-located tests: tests/agentic/gate-checks/*.test.ts (one suite per production check module), tests/agentic/gate-shared/*.test.ts (markdown helpers, file walkers), and tests/agentic/analysis-gate-integration.test.ts (end-to-end orchestrator scenarios)
  • ESLint clean with zero warnings
  • No circular dependencies (barrel imports only)

Political Intelligence Validation Pipeline

The political intelligence generation and validation is a CI/CD concern enforced both in the prebuild chain and within agentic workflows:

Prebuild Chain (13 Steps)

generate-article-types-doc โ†’ copy-vendor-mermaid โ†’ aggregate-analysis โ†’ render-articles โ†’
generate-news-indexes โ†’ extract-news-metadata โ†’ generate-sitemap-html โ†’
generate-political-intelligence โ†’ generate-rss โ†’ generate-sitemap โ†’
normalize-static-html-chrome โ†’ backfill-translated-chrome โ†’ strip-legacy-chrome-script-tags

Analysis Gate Enforcement

Every agentic news workflow MUST produce 23 analysis artifacts (Families A-D) and pass the analysis gate (scripts/agentic/analysis-gate.ts) before article rendering:

CheckValidationScript
1Artifact existence (23 files)analysis-gate.ts
2No stub placeholders (AI_MUST_REPLACE, [REQUIRED], TODO:)analysis-gate.ts
3Minimum word count per artifactanalysis-gate.ts
4Evidence citations (SWOT + significance)analysis-gate.ts
5Mermaid diagrams with colour configurationanalysis-gate.ts
6Pass-2 evidence (revision proof via mtime/snapshot diff)analysis-gate.ts
7Cross-references between artifactsanalysis-gate.ts
8Data-source connectivity auditanalysis-gate.ts
9aPolitical classification completenessanalysis-gate.ts
9bAgency evidence (Statskontoret recognised agencies)analysis-gate.ts

Additional Validation Scripts

ScriptPurposeTrigger
validate-methodology-reflection.tsValidates methodology-reflection.md structure and required sectionsAgentic workflow
validate-quality-scores.cjsValidates quality score thresholdsCI quality checks
validate-article.tsValidates article HTML structure and metadataPrebuild + CI
validate-news-translations.tsDetects remaining data-translate markersTranslation validation workflow
validate-translations.tsValidates all translation filesCI

Parliamentary Data Scripts

ScriptPurposeSchedule
download-parliamentary-data.tsDownload propositions, motions, betรคnkanden from Riksdag APINightly / on-demand
fetch-voting-records.tsFetch voting records from RiksdagNightly
fetch-calendar.tsFetch parliamentary calendar eventsNightly
fetch-statskontoret.tsFetch Statskontoret agency data (headcount, budget)Weekly
fetch-rir-followups.tsFetch Riksrevisionen follow-up reportsWeekly
scb-fetch.tsFetch SCB statistical dataOn-demand
imf-fetch.tsFetch IMF economic data (WEO, FM, IFS, DOTS)On-demand

๐Ÿ”’ Workflow Security Architecture

Supply Chain Security

All workflows implement defense-in-depth:

flowchart TB
    subgraph "๐Ÿ›ก๏ธ Defense-in-Depth Layers"
        L1[๐Ÿ”’ Layer 1: Permissions Hardening] --> L2[๐Ÿ“Œ Layer 2: SHA Pinning]
        L2 --> L3[๐Ÿ›ก๏ธ Layer 3: Runner Hardening]
        L3 --> L4[๐Ÿ“ฆ Layer 4: Dependency Scanning]
        L4 --> L5[๐Ÿ” Layer 5: Code Scanning]
        L5 --> L6[๐Ÿ“ก Layer 6: Runtime Monitoring]
    end

    subgraph "๐Ÿ” Controls per Layer"
        L1 -.-> C1[Least privilege permissions]
        L2 -.-> C2[Immutable action references]
        L3 -.-> C3[step-security/harden-runner]
        L4 -.-> C4[Dependency Review + Dependabot]
        L5 -.-> C5[CodeQL + Scorecard]
        L6 -.-> C6[Uptime + Lighthouse]
    end

    classDef layer fill:#e74c3c,stroke:#c0392b,stroke-width:1.5px,color:white
    classDef control fill:#3498db,stroke:#2980b9,stroke-width:1.5px,color:white

    class L1,L2,L3,L4,L5,L6 layer
    class C1,C2,C3,C4,C5,C6 control
ControlImplementationISMS Reference
๐Ÿ”’ Action SHA PinningEvery uses: pinned to commit SHACIS 16.6
๐Ÿ›ก๏ธ Harden Runnerstep-security/harden-runner with egress auditNIST DE.CM-1
๐Ÿ” Least PrivilegeMinimal permissions: per-workflowISO A.8.3
๐Ÿ“ฆ Dependency Reviewactions/dependency-review-action on PRsCIS 16.4
๐Ÿ” CodeQL Scanningjavascript-typescript language matrixISO A.8.8
โญ ScorecardOpenSSF Scorecard supply-chain analysisNIST PR.DS-6
๐Ÿ”‘ Secret ScanningNative GitHub secret scanning enabledISO A.8.24

Secrets Management

Secret / CredentialUsed ByPurpose
GITHUB_TOKENMost workflowsStandard GitHub API access
COPILOT_MCP_GITHUB_PERSONAL_ACCESS_TOKENCopilot setup, agentic workflowsMCP server authentication
AWS OIDC Role (GithubWorkFlowRole)deploy-s3, releaseEphemeral credentials via id-token: write + role-to-assume
CloudFront Distribution IDdeploy-s3, releaseDiscovered dynamically from CloudFormation stack or origin lookup

๐Ÿ—๏ธ gh-aw (GitHub Agentic Workflows) Security Architecture

Reference: gh-aw Architecture ยท SECURITY_ARCHITECTURE.md ยง Five-Layer Safe-Output Model

All 14 agentic workflows in this repository execute within the gh-aw runtime โ€” GitHub's purpose-built security substrate for AI-powered automation. gh-aw enforces a three-layer defense-in-depth model that contains agent actions within strict trust boundaries.

๐Ÿ›๏ธ Three-Layer Trust Model

flowchart TB
    subgraph L1["๐Ÿ”’ Layer 1: Substrate-Level Trust<br/>(Infrastructure โ€” enforced by gh-aw runtime)"]
        direction LR
        AWF["๐Ÿงฑ Agent Workflow Firewall<br/>(iptables + Squid proxy)"]
        MCP_GW["๐Ÿณ MCP Gateway<br/>(Docker container isolation)"]
        API_P["๐Ÿ”Œ API Proxy<br/>(token-scoped access)"]
        VM["๐Ÿ–ฅ๏ธ Runner VM<br/>(ephemeral, kernel-hardened)"]
    end

    subgraph L2["โš™๏ธ Layer 2: Configuration-Level Trust<br/>(Compile-time โ€” enforced by gh aw compile)"]
        direction LR
        SCHEMA["๐Ÿ“‹ Schema Validation<br/>(workflow structure)"]
        SHA["๐Ÿ“Œ Action SHA Pinning<br/>(immutable references)"]
        SCAN["๐Ÿ” Security Scanners<br/>(actionlint, zizmor, poutine)"]
        STRICT["๐Ÿ” Strict Mode<br/>(expression allowlisting)"]
    end

    subgraph L3["๐Ÿ›ก๏ธ Layer 3: Plan-Level Trust<br/>(Runtime โ€” enforced per execution)"]
        direction LR
        SO["๐Ÿ“ค SafeOutputs<br/>(buffered writes)"]
        TD["๐Ÿ•ต๏ธ Threat Detection<br/>(AI-powered analysis)"]
        CS["๐Ÿงน Content Sanitisation<br/>(@mention, URI, tag filters)"]
        SR["๐Ÿ”‘ Secret Redaction<br/>(pre-upload scan)"]
    end

    L1 --> L2 --> L3

    style L1 fill:#1a237e,color:#fff,stroke:#0d47a1,stroke-width:2px
    style L2 fill:#004d40,color:#fff,stroke:#00695c,stroke-width:2px
    style L3 fill:#b71c1c,color:#fff,stroke:#c62828,stroke-width:2px

๐Ÿงฑ Layer 1: Substrate-Level Trust (Infrastructure)

The gh-aw runtime provides hardware-enforced isolation for every agentic workflow run:

ComponentIconFunctionRiksdagsmonitor Usage
Runner VM๐Ÿ–ฅ๏ธEphemeral GitHub Actions VM with kernel-level isolation; destroyed after each runAll 14 agentic workflows execute in fresh VMs
Agent Workflow Firewall (AWF)๐Ÿงฑiptables redirects all HTTP/HTTPS through a Squid proxy with domain allowlist; non-allowlisted traffic is DROPped17 allowlisted domains (see Network egress allow-list)
MCP Gateway๐ŸณEach MCP server runs in an isolated Docker container; tool allowlisting; per-container network controls; secrets injected via env vars onlyscb and world-bank servers in node:26-alpine containers
API Proxy๐Ÿ”ŒToken-scoped access to GitHub APIs; prevents privilege escalation via stolen tokensAgentic workflows get read-only repo + PR write only

โš™๏ธ Layer 2: Configuration-Level Trust (Compile-Time)

The gh aw compile command enforces security at compilation time:

ControlIconWhat It EnforcesRiksdagsmonitor Implementation
Schema Validation๐Ÿ“‹Workflow YAML structure must conform to gh-aw schema (permissions, triggers, steps)compile-agentic-workflows.yml validates all 14 .md sources
Expression Allowlisting๐Ÿ”Only safe expression patterns allowed in workflow definitionsStrict mode enabled; no ${{ }} in shell commands
Action SHA Pinning๐Ÿ“ŒAll uses: references pinned to immutable commit SHAs (not tags)100% SHA-pinned across all 54 workflow files
Security Scanners๐Ÿ”actionlint, zizmor, poutine run during compilationIntegrated into the compile workflow quality gate
Prompt Module Size Cap๐Ÿ“No single prompt module may exceed 550 linesEnforced by compile workflow (prevents prompt injection via oversized modules)

๐Ÿ›ก๏ธ Layer 3: Plan-Level Trust (Runtime)

Runtime controls that govern what the AI agent can actually do:

ControlIconMechanismRiksdagsmonitor Implementation
SafeOutputs๐Ÿ“คAgent job has read-only permissions; all writes buffered as artifacts; separate detection job analyzes before executionFive-layer validator: sanitise โ†’ schema โ†’ policy โ†’ human review โ†’ merge
Threat Detection Pipeline๐Ÿ•ต๏ธSeparate job downloads agent artifacts; AI security agent analyzes for secret leaks, malicious patches, policy violations; blocking verdict gates output jobsAnalysis gate (checks 1โ€“9b) + methodology-reflection validator
Content Sanitisation๐Ÿงน@mention neutralisation, bot trigger protection, XML/HTML tag conversion, URI filtering (HTTPS-only from trusted domains), content size limits (0.5 MB / 65k lines)rehype-sanitize allow-list + Mermaid securityLevel: 'strict'
Integrity Filtering๐Ÿ”’Controls which GitHub content the agent can access based on author trust and merge statusRepository scoped โ€” merged > approved > unapproved
Secret Redaction๐Ÿ”‘Automatic scanning of /tmp/gh-aw for secrets before artifact upload; partial visibility (first 3 chars + ***)Enforced by gh-aw runtime for all 14 workflows

๐Ÿ”„ SafeOutputs Execution Flow

sequenceDiagram
    participant Agent as ๐Ÿค– AI Agent (read-only)
    participant Buffer as ๐Ÿ“ฆ Artifact Buffer
    participant Detect as ๐Ÿ•ต๏ธ Threat Detection Job
    participant Gate as โ›” Analysis Gate
    participant Output as ๐Ÿ“ค Safe Output Jobs
    participant Human as ๐Ÿ‘ค Human Reviewer

    Agent->>Buffer: Write analysis artifacts + article
    Note over Agent,Buffer: Agent has NO write permissions<br/>All output buffered as workflow artifacts

    Buffer->>Detect: Download artifacts for analysis
    Detect->>Detect: AI security scan (secret leaks, malicious patches)
    Detect->>Gate: Structural validation (checks 1โ€“9b)

    alt Detection PASS + Gate PASS
        Gate->>Output: Authorize safe output execution
        Output->>Output: create_pull_request (sanitised content)
        Output->>Human: PR ready for review
        Human->>Human: Approve or reject
    else Detection FAIL or Gate FAIL
        Gate--xOutput: โŒ Blocked โ€” no PR created
        Note over Gate,Output: Fail-closed: entire workflow fails
    end

๐ŸŒ gh-aw Security Components Applied to Riksdagsmonitor

flowchart LR
    subgraph "14 Agentic News Workflows"
        W1["news-propositions"]
        W2["news-motions"]
        W3["news-committee-reports"]
        W4["โ€ฆ + 11 more"]
    end

    subgraph "gh-aw Security Substrate"
        FW["๐Ÿงฑ AWF<br/>Squid + iptables<br/>17 domains allowed"]
        MCP["๐Ÿณ MCP Gateway<br/>3 containerised servers"]
        SO["๐Ÿ“ค SafeOutputs<br/>5-layer validator"]
        TD["๐Ÿ•ต๏ธ Threat Detection<br/>AI + structural gates"]
        SR["๐Ÿ”‘ Secret Redaction<br/>Pre-upload scan"]
    end

    subgraph "Riksdagsmonitor Controls"
        AG["โ›” Analysis Gate<br/>Checks 1โ€“9b"]
        MR["๐Ÿ“Š Methodology<br/>Reflection Validator"]
        PR["๐Ÿ‘ค Human PR Review<br/>CODEOWNERS"]
    end

    W1 & W2 & W3 & W4 --> FW
    FW --> MCP
    MCP --> SO
    SO --> TD
    TD --> AG
    AG --> MR
    MR --> PR

    style FW fill:#1a237e,color:#fff
    style MCP fill:#004d40,color:#fff
    style SO fill:#b71c1c,color:#fff
    style TD fill:#e65100,color:#fff
    style SR fill:#4a148c,color:#fff
    style AG fill:#880e4f,color:#fff

๐Ÿ“Š gh-aw Security Layer Summary

LayerTrust BoundaryEnforced ByBypass ResistanceISMS Mapping
๐Ÿ”’ L1: SubstrateInfrastructuregh-aw runtime (VM + kernel + AWF + MCP Gateway)Hardware isolation; iptables DROP rules; container sandboxingISO A.8.22 (Network segregation), NIST PR.AC-5, CIS #13
โš™๏ธ L2: ConfigurationCompilationgh aw compile + security scannersSchema validation; SHA immutability; scanner verdictsISO A.8.28 (Secure coding), NIST PR.DS-6, CIS #16.6
๐Ÿ›ก๏ธ L3: PlanRuntimeSafeOutputs + threat detection + sanitisationPermission separation; AI-powered analysis; fail-closed gatesISO A.8.25 (SDLC), NIST DE.CM-4, CIS #16.10

๐Ÿ“Š ISMS Compliance Mapping

ISO 27001:2022 Controls

ControlWorkflow(s)Implementation
A.5.33 โ€” Protection of recordsupdate-cia-csv-dataGit audit trail, source attribution, automated PR review
A.5.36 โ€” Conformity with policiesscorecardsOpenSSF automated compliance
A.5.37 โ€” Documented proceduresAllWorkflow YAML as executable documentation
A.8.3 โ€” Information lifecycleupdate-cia-csv-dataNightly upstream refresh, change-detection, PR-gated commits
A.8.8 โ€” Vulnerability managementcodeql, dependency-reviewAutomated scanning
A.8.10 โ€” Information deletionupdate-cia-csv-dataBranch auto-delete after PR merge
A.8.19 โ€” Security in useAllHTTPS-only, SRI, CSP
A.8.24 โ€” Secret scanningGitHub nativeAutomated secret detection
A.8.31 โ€” Separation of environmentsreleaseStaging โ†’ production pipeline
A.8.32 โ€” Change managementquality-checks, testingQuality gates before merge

NIST CSF 2.0 Functions

FunctionWorkflow(s)Implementation
GV (Govern)setup-labels, ISMS documentationPolicy enforcement through automation
ID (Identify)scorecards, dependency-reviewAsset and vulnerability identification
PR (Protect)codeql, harden-runner, SHA pinningSecurity controls implementation
DE (Detect)uptime-monitor, update-cia-csv-dataContinuous monitoring and upstream change detection
RS (Respond)Incident auto-creation on outageAutomated incident response
RC (Recover)Auto-close incidents on recoveryAutomated recovery verification

CIS Controls v8.1

ControlWorkflow(s)Implementation
2.2 โ€” Software inventoryrelease (SBOM)Automated SBOM generation
3.1 โ€” Data inventoryupdate-cia-csv-dataExplicit tracked-file discovery + recursive upstream index
3.14 โ€” Data integrityupdate-cia-csv-dataByte-level diff vs upstream + PR review gate
16.2 โ€” Software securityscorecardsSupply chain assessment
16.4 โ€” Dependency securitydependency-reviewVulnerability scanning
16.6 โ€” Application securitycodeqlStatic analysis
16.10 โ€” Vulnerability remediationDependabot + codeqlAutomated patching

๐Ÿงฐ Cache and External-Registry Resilience Standard

Cache Strategy (standard workflows)

  • Primary cache mechanism: actions/setup-node built-in npm cache (cache: 'npm'), with explicit cache-dependency-path including:
    • package-lock.json
    • the owning workflow file path (for per-workflow cache key uniqueness)
  • Single direct actions/cache usage: only dependency-review.yml (apt archive cache), pinned to:
    • actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
  • Cache invalidation: key version prefixes (e.g., -v2-) are used to force expiration of prior cache generations when strategy changes.
  • Cache TTL note: GitHub Actions does not support per-workflow explicit cache expiration/TTL configuration; retention is managed by the GitHub cache eviction policy and repository cache storage limits (10 GB per repository).

Resilience requirements (registry / apt / browser tooling)

  • Add retry + exponential backoff for apt-get update and apt-get install in workflows that install system dependencies.
  • Add retry + npm fetch-retry tuning (fetch-retries=5, fetch-retry-mintimeout=20000, fetch-retry-maxtimeout=120000) for global npm installs and npm ci in setup-heavy workflows.
  • Add step-level timeout-minutes on dependency-install steps most exposed to external outage/hanging behavior.
  • Prefer browser/binary installs without extra apt dependency fetches where possible (e.g., Playwright browser-only install).

๐Ÿ› ๏ธ Workflow Troubleshooting Guide

Common Issues and Solutions

IssueCauseSolution
๐Ÿ”ด TypeScript type-check failsMissing module or incorrect importVerify tsconfig.browser.json includes the file; run npx tsc --project tsconfig.browser.json --noEmit locally
๐Ÿ”ด Workflow not triggering on TS changesMissing path filterAdd '**/*.ts' and 'src/browser/**' to path filters
๐Ÿ”ด Node version cannot run .ts scriptsOlder Node.js versionNode 26 has native TS type-stripping; verify node -e "console.log(process.features.typescript)" outputs "strip"
๐Ÿ”ด Harden Runner egress failuresNew network endpoints accessedReview egress report and add legitimate endpoints to allowed-endpoints
๐Ÿ”ด Lighthouse CI failuresPerformance regressionCheck Lighthouse HTML report artifact; optimize images, reduce CSS, fix color contrast
๐Ÿ”ด Data pipeline skipping fetchData freshness < 23 hoursUse force_refresh: true input for manual dispatch
๐Ÿ”ด Agentic lock files outdated.md source edited but not compiledRun gh aw compile .github/workflows/<name>.md and commit .lock.yml
๐Ÿ”ด Translation validation failingMissing hreflang or language purityRun npm run validate-translations locally
๐Ÿ”ด Deploy-S3 CloudFront invalidationOIDC role trust or IAM permissions misconfigured, or CloudFront distribution ID lookup from CloudFormation failedVerify GitHub OIDC provider + role trust policy, ensure the assumed role has required CloudFront/S3/CloudFormation permissions, and confirm the workflow step that discovers the distribution ID from the CloudFormation stack/origin is succeeding

๐Ÿ“ˆ Workflow Metrics

Key Performance Indicators

MetricTargetActualStatus
Test Count> 10007,500+โœ…
Test Pass Rate100%100%โœ…
TypeScript Errors00โœ…
ESLint Errors00โœ…
Build Time< 5s3.4sโœ…
Test DurationTracked in CI139s local full suiteโœ…
Action SHA Pinning100%100%โœ…
Harden RunnerAll workflowsAllโœ…
Language Coverage1414โœ…
Agentic Workflows1414โœ…

๐Ÿ“š References

ISMS Documentation

GitHub Documentation

External Tools


๐Ÿ“‹ Document Owner: CEO | ๐Ÿ“„ Version: 7.6 | ๐Ÿ“… Last Updated: 2026-06-02 (UTC) ๐Ÿ”„ Review Cycle: Quarterly | โฐ Next Review: 2026-09-02 ๐Ÿข Classification: Public | ๐Ÿ›๏ธ Owner: Hack23 AB (Org.nr 5595347807)


๐Ÿ”— Hack23 Ecosystem

๐ŸŒ Platforms ๐Ÿ“ฆ Open-Source Projects ๐Ÿ›ก๏ธ Governance & Standards
๐Ÿ—ณ๏ธ Riksdagsmonitor โ€” Swedish Parliament intelligence
๐Ÿ‡ช๐Ÿ‡บ EU Parliament Monitor โ€” European coverage
๐Ÿ•ต๏ธ Citizen Intelligence Agency โ€” political-data engine
๐ŸŒ Hack23 AB โ€” corporate site
๐Ÿ“ฐ Hack23 Blog โ€” engineering & policy
๐Ÿ’ผ Hack23 on LinkedIn
๐Ÿ—ณ๏ธ Hack23/riksdagsmonitor
๐Ÿ•ต๏ธ Hack23/cia
๐Ÿ‡ช๐Ÿ‡บ Hack23/euparliamentmonitor
๐Ÿ”Œ Hack23/european-parliament-mcp
โœ… Hack23/cia-compliance-manager
๐Ÿฅ‹ Hack23/black-trigram
๐Ÿ  Hack23/homepage
๐Ÿ›ก๏ธ Hack23 ISMS-PUBLIC โ€” public ISMS
๐Ÿ”’ Information Security Policy
๐Ÿค– AI Policy
๐Ÿงช Secure Development Policy
๐ŸŽฏ Threat Modeling Policy
โš ๏ธ Vulnerability Management
๐Ÿท๏ธ Classification Framework

OpenSSF Best Practices OpenSSF Scorecard ISO 27001:2022 NIST CSF 2.0 CIS Controls v8.1 Apache 2.0

๐Ÿ—ณ๏ธ Empower citizens ยท ๐Ÿ” Strengthen democratic accountability ยท ๐Ÿ•ต๏ธ Illuminate the political process

ยฉ 2008โ€“2026 Hack23 AB (Org.nr 559534-7807) ยท Maintainer: James Pether Sรถrling, CISSP CISM