riksdagsmonitor 0.8.54 β 0.8.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -4
- package/SECURITY.md +46 -0
- package/package.json +17 -5
package/README.md
CHANGED
|
@@ -725,12 +725,43 @@ flowchart LR
|
|
|
725
725
|
|
|
726
726
|
## π€ AI-Disrupted News Generation
|
|
727
727
|
|
|
728
|
-
> *"While traditional newsrooms debate whether AI will replace journalists, Riksdagsmonitor already runs a fully autonomous political intelligence newsroom β
|
|
728
|
+
> *"While traditional newsrooms debate whether AI will replace journalists, Riksdagsmonitor already runs a fully autonomous political intelligence newsroom β 11 agentic workflows, 14 languages, zero human editors, and a publication schedule that would bankrupt any legacy outlet trying to keep up."*
|
|
729
729
|
|
|
730
|
-
Riksdagsmonitor's **agentic news generation pipeline** is the world's first fully AI-driven political intelligence newsroom for parliamentary monitoring. Powered by Claude Opus (currently 4.7) via GitHub Copilot Coding Agent, our **
|
|
730
|
+
Riksdagsmonitor's **agentic news generation pipeline** is the world's first fully AI-driven political intelligence newsroom for parliamentary monitoring. Powered by Claude Opus (currently 4.7) via GitHub Copilot Coding Agent, our **11 specialized workflows** (10 single-run news pipelines + 1 dedicated translation workflow) autonomously produce deep political analysis β not shallow summaries, but structured intelligence products with source verification, multi-party balance, and GDPR-compliant OSINT methodology.
|
|
731
|
+
|
|
732
|
+
### 𧬠Pipeline at a glance
|
|
733
|
+
|
|
734
|
+
```mermaid
|
|
735
|
+
flowchart LR
|
|
736
|
+
A[MCP servers<br/>Riksdag Β· SCB Β· World Bank] --> B[Analysis artifacts<br/>analysis/daily/$DATE/$SUB/<br/>9 core or 14 Tier-C .md files]
|
|
737
|
+
M[analysis/methodologies/<br/>analysis/templates/] --> B
|
|
738
|
+
B --> C[scripts/aggregate-analysis.ts<br/>Concatenate Β· strip dups Β· rewrite links Β· emit manifest]
|
|
739
|
+
C --> D[article.md<br/>Canonical aggregated markdown]
|
|
740
|
+
D --> E[scripts/render-articles.ts<br/>+ scripts/render-lib/<br/>unified Β· remark Β· rehype Β· sanitize]
|
|
741
|
+
E --> F[news/$DATE-$SUB-en.html<br/>news/$DATE-$SUB-sv.html]
|
|
742
|
+
F --> G[news-translate workflow<br/>EN+SV β 12 other languages<br/>OUT-OF-BAND]
|
|
743
|
+
F --> S[sitemap.xml + sitemap.html<br/>rss.xml<br/>political-intelligence_*.html]
|
|
744
|
+
G --> S
|
|
745
|
+
|
|
746
|
+
style C fill:#2196f3,color:#fff
|
|
747
|
+
style E fill:#4caf50
|
|
748
|
+
style G fill:#9e9e9e,color:#fff
|
|
749
|
+
```
|
|
750
|
+
|
|
751
|
+
A new `.md` artifact written anywhere under `analysis/daily/$DATE/$SUB/` is enough to produce a published English + Swedish HTML article on the next CI build β there is no manual scaffolding step, no template fill-in, and no per-type generator class. The news workflows themselves never write localised HTML; that is the sole responsibility of `news-translate`.
|
|
752
|
+
|
|
753
|
+
### π Anatomy of an article
|
|
754
|
+
|
|
755
|
+
Every published article is a deterministic projection of three input sources, in this priority:
|
|
756
|
+
|
|
757
|
+
1. **`analysis/methodologies/`** β the *editorial method* (e.g. STRIDE, devil's-advocate, ACH, comparative-politics framing). These files define **how** an analysis is conducted; they are version-controlled and cited from every article footer.
|
|
758
|
+
2. **`analysis/templates/`** β the *output structure* (executive-brief, synthesis, significance, stakeholders, SWOT, scenarios, comparative, intel-assessment, classification, β¦). These define **what sections** appear and in **what order**.
|
|
759
|
+
3. **`analysis/daily/$DATE/$SUB/*.md`** β the *evidence* (per-day artifacts produced by the agentic workflow's analysis phase). These provide the **specific facts**, MCP query results, and per-document analyses for one day's coverage.
|
|
760
|
+
|
|
761
|
+
The aggregator concatenates the day's evidence in template order (with `intelligence-assessment.md` β the ICD-203 Key Judgments centrepiece β surfaced at position 3 immediately after the executive brief + synthesis), the renderer transforms the markdown into sanitised HTML, and the chrome layer wraps it with JSON-LD, a tagline-and-breadcrumb header, a 3-column footer (*Riksdagsmonitor* / *Resources* / *Trust & compliance*) and both a dropdown and an always-visible footer language switcher. The chrome's language switcher populates `hreflangAlternates` for **all 14 supported languages** at render time, so switching language from any article always lands on the sibling article (e.g. `news/2026-04-24-propositions-de.html`), never on the language homepage. Internally, `scripts/render-lib/` is split into six focused leaf modules β `aggregator.ts`, `markdown.ts`, `chrome.ts`, `article.ts`, `url-helpers.ts`, `constants.ts` β behind a thin barrel `index.ts`; see [`ARCHITECTURE.md`](ARCHITECTURE.md#pipeline-stages) for the full per-module contract. The `Sources of Method` block in every article footer links back to every methodology and template file actually used β provenance is preserved end-to-end.
|
|
731
762
|
|
|
732
763
|
> π **Directory-level catalogs** (single sources of truth):
|
|
733
|
-
> - [`.github/workflows/README.md`](.github/workflows/README.md) β 45 workflow files (21 standard `.yml` +
|
|
764
|
+
> - [`.github/workflows/README.md`](.github/workflows/README.md) β 45 workflow files (21 standard `.yml` + 11 agentic `.md` sources + 11 compiled `.lock.yml`)
|
|
734
765
|
> - [`.github/prompts/README.md`](.github/prompts/README.md) β 8 bounded-context prompt modules + `ext/tier-c-aggregation.md`, imported by every news workflow
|
|
735
766
|
> - [`.github/agents/README.md`](.github/agents/README.md) β 24 Copilot agent files (14 personas + 9 workflow-specialists + 1 shared developer-instructions)
|
|
736
767
|
> - [`.github/skills/README.md`](.github/skills/README.md) β 91 skills grouped by 12 functional categories
|
|
@@ -756,7 +787,6 @@ Every day, the platform's AI operatives awaken on cron schedules, query the Swed
|
|
|
756
787
|
| π 18:00 (16:00 Sat) | **Evening Analysis** | Deep-dive intelligence synthesis | MonβSat |
|
|
757
788
|
| π 09:00 | **Weekly Review** | Week-in-review scorecard, party performance | Saturday |
|
|
758
789
|
| π 10:00 | **Monthly Review** | Comprehensive monthly intelligence assessment | 28th of month |
|
|
759
|
-
| π§ Manual | **Article Generator** | On-demand article generation / backfill | On-demand |
|
|
760
790
|
|
|
761
791
|
> _All times are **UTC** (GitHub Actions cron). For local time, convert to CET/CEST. Authoritative schedules defined in `.github/workflows/news-*.lock.yml` workflows β see [`.github/workflows/README.md`](.github/workflows/README.md) for the complete inventory._
|
|
762
792
|
|
|
@@ -1060,3 +1090,21 @@ CEO, Hack23 AB
|
|
|
1060
1090
|
|
|
1061
1091
|
*Monitor political activity in Sweden with systematic transparency*
|
|
1062
1092
|
|
|
1093
|
+
|
|
1094
|
+
|
|
1095
|
+
---
|
|
1096
|
+
|
|
1097
|
+
## π Authoritative Data Sources (Current State)
|
|
1098
|
+
|
|
1099
|
+
Riksdagsmonitor uses a **provider-tiered** data architecture, with each provider chosen for its area of strength. As of **2026-04-24**, all four providers are implemented and in production.
|
|
1100
|
+
|
|
1101
|
+
| Tier | Provider | Scope | Access |
|
|
1102
|
+
|---|---|---|---|
|
|
1103
|
+
| **Primary economic** | **IMF** (Datamapper REST + SDMX 3.0) | GDP, growth, unemployment, inflation, fiscal balance, debt, current account, bilateral trade, commodity prices, exchange rates, government spending by COFOG function β including T+5 projections | Pure-TypeScript client `scripts/imf-client.ts` (intentionally non-MCP) |
|
|
1104
|
+
| **Parliamentary primary** | **Riksdagen Open Data** | Documents, motions, votes, MPs, speeches | `riksdag-regering` MCP server |
|
|
1105
|
+
| **Swedish ground truth** | **SCB** (PxWeb v2) | Swedish monthly labour (AKU), monthly inflation (KPI), regional/municipal, budget execution | `scb` MCP server |
|
|
1106
|
+
| **Non-economic residue** | **World Bank** | Governance (WGI), environment, social/education residue, defence-spending depth | `world-bank` MCP server |
|
|
1107
|
+
|
|
1108
|
+
**Why this split** β IMF uses uniform SNA 2008 / GFSM 2014 / BPM6 methodology across countries (essential for cross-country comparison), publishes T+5 projections (essential for look-ahead workflows), and has fresher data than World Bank's economic indicators. World Bank remains the canonical source for the classes IMF does not publish (WGI governance, environment).
|
|
1109
|
+
|
|
1110
|
+
Authority: [`.github/aw/ECONOMIC_DATA_CONTRACT.md`](.github/aw/ECONOMIC_DATA_CONTRACT.md) v2.1 Β· hub: [`analysis/imf/`](analysis/imf/) Β· agent guide: [`AGENTS.md`](AGENTS.md) Β§IMF.
|
package/SECURITY.md
CHANGED
|
@@ -75,6 +75,20 @@ A vulnerability is a weakness or flaw in the project that can be exploited to co
|
|
|
75
75
|
- Supply chain vulnerabilities in dependencies
|
|
76
76
|
- Content injection through data pipelines
|
|
77
77
|
|
|
78
|
+
### In-scope components
|
|
79
|
+
|
|
80
|
+
The following components are within the disclosure scope and welcome responsible-disclosure reports:
|
|
81
|
+
|
|
82
|
+
- **Static site** β all HTML/CSS/JS served from `/` and `/dashboard/` and `/news/`.
|
|
83
|
+
- **News generation pipeline**:
|
|
84
|
+
- `scripts/aggregate-analysis.ts` β concatenates `analysis/daily/$DATE/$SUB/` artifacts into `article.md` + SHA-256 manifest.
|
|
85
|
+
- `scripts/render-articles.ts` β markdown β sanitised HTML pipeline.
|
|
86
|
+
- `scripts/render-lib/` β shared chrome (header, footer, language switcher, JSON-LD `NewsArticle` shell) and the `rehype-sanitize` allow-list.
|
|
87
|
+
- `scripts/validate-news-translations.ts` β translation-completeness validator.
|
|
88
|
+
- **Index generators** β `scripts/generate-sitemap*.ts`, `scripts/generate-rss.ts`, `scripts/generate-news-indexes.ts`, `scripts/generate-political-intelligence.ts`.
|
|
89
|
+
- **Agentic workflows** β 11 workflows in `.github/workflows/news-*.md` + their compiled `.lock.yml` peers, plus the non-agentic CI/CD pipelines in `.github/workflows/`.
|
|
90
|
+
- **MCP configuration** β `.github/copilot-mcp.json` and per-workflow `mcp-servers:` blocks.
|
|
91
|
+
|
|
78
92
|
### How to Privately Report a Vulnerability using GitHub
|
|
79
93
|
|
|
80
94
|
1. On GitHub.com, navigate to the main page of the [riksdagsmonitor repository](https://github.com/Hack23/riksdagsmonitor).
|
|
@@ -152,3 +166,35 @@ Riksdagsmonitor's security practices are part of Hack23 AB's comprehensive Infor
|
|
|
152
166
|
**π
Effective Date:** 2026-02-20
|
|
153
167
|
**β° Next Review:** 2026-05-20
|
|
154
168
|
**π― Framework Compliance:** [](https://github.com/Hack23/ISMS-PUBLIC/blob/main/CLASSIFICATION.md) [](https://github.com/Hack23/ISMS-PUBLIC/blob/main/CLASSIFICATION.md) [](https://github.com/Hack23/ISMS-PUBLIC/blob/main/CLASSIFICATION.md)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## π IMF Integration β Security Disclosure Note
|
|
174
|
+
|
|
175
|
+
> **Effective:** 2026-04-24 Β· **Authoritative hub:** [`analysis/imf/README.md`](analysis/imf/README.md) Β· [`analysis/imf/agentic-integration.md`](analysis/imf/agentic-integration.md) Β· [`analysis/imf/indicators-inventory.json`](analysis/imf/indicators-inventory.json) Β· [`analysis/imf/data-dictionary.md`](analysis/imf/data-dictionary.md) Β· [`.github/aw/ECONOMIC_DATA_CONTRACT.md`](.github/aw/ECONOMIC_DATA_CONTRACT.md)
|
|
176
|
+
|
|
177
|
+
### IMF data scope
|
|
178
|
+
|
|
179
|
+
Riksdagsmonitor consumes **public, anonymous, unauthenticated** macro/fiscal/monetary statistics from the IMF Datamapper REST API (`www.imf.org/external/datamapper/api/v1`) and the IMF SDMX 3.0 endpoint (`sdmxcentral.imf.org`). **No personal data, no credentials, no auth tokens** are exchanged with the IMF. The IMF integration is therefore out of scope for GDPR DPIA but in scope for this security policy as a third-party dependency.
|
|
180
|
+
|
|
181
|
+
### IMF-specific security posture
|
|
182
|
+
|
|
183
|
+
| Control | Implementation |
|
|
184
|
+
|---|---|
|
|
185
|
+
| Transport | HTTPS-only Β· TLS 1.3 Β· pinned hostnames in egress allow-list |
|
|
186
|
+
| Integrity | SHA-256 payload pin per (dataflow, indicator, country, vintage); supersedes-chain in cache |
|
|
187
|
+
| Vintage discipline | Reject payloads >6 months old without staleness annotation (ECONOMIC_DATA_CONTRACT v2.1) |
|
|
188
|
+
| Rate-limit guard | β€30 req/min self-imposed; exponential back-off |
|
|
189
|
+
| Supply chain | `scripts/imf-*.ts` reviewed in-repo; no dynamic eval; harden-runner egress audit |
|
|
190
|
+
| Licence | Attribution-required; auto-emitted in article footer template |
|
|
191
|
+
|
|
192
|
+
### Reporting IMF-related vulnerabilities
|
|
193
|
+
|
|
194
|
+
If you discover a vulnerability in our IMF integration (e.g., cache integrity bypass, vintage substitution, egress allow-list breakout), follow the standard vulnerability-disclosure flow above. IMF data is public, so confidentiality breaches are not a concern; integrity and availability are the relevant attack surfaces.
|
|
195
|
+
|
|
196
|
+
### IMF egress allow-list
|
|
197
|
+
|
|
198
|
+
**Egress hosts** (allow-list): `www.imf.org` (Datamapper REST Β· WEO/FM), `sdmxcentral.imf.org` (SDMX 3.0 REST Β· IFS/BOP/DOTS/GFS/PCPS/ER/MFS_IR/MFS_PR). Both HTTPS-only, anonymous, public β no credentials required.
|
|
199
|
+
|
|
200
|
+
**Canonical rule.** Every economic claim in a Riksdagsmonitor article cites an IMF dataflow first; World Bank citations are reserved for governance, environment and social residue (the classes IMF does not publish). SCB is the Swedish-specific ground truth layer. See `ECONOMIC_DATA_CONTRACT.md` v2.1 for the banned-phrase list and vintage discipline (>6 mo β annotation).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "riksdagsmonitor",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.55",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Swedish Parliament (Riksdag) intelligence platform β TypeScript utilities for political data visualization, dashboards, and open data analysis with Chart.js and D3.js",
|
|
6
6
|
"main": "dist/lib/shared/index.js",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"dev": "vite",
|
|
51
|
-
"prebuild": "npx tsx scripts/generate-news-indexes/index.ts && npx tsx scripts/extract-news-metadata.ts && npx tsx scripts/generate-sitemap-html.ts && npx tsx scripts/generate-political-intelligence.ts && npx tsx scripts/generate-rss.ts && npx tsx scripts/generate-sitemap.ts",
|
|
51
|
+
"prebuild": "npx tsx scripts/aggregate-analysis.ts --all --quiet && npx tsx scripts/render-articles.ts --all --lang en,sv --quiet && npx tsx scripts/generate-news-indexes/index.ts && npx tsx scripts/extract-news-metadata.ts && npx tsx scripts/generate-sitemap-html.ts && npx tsx scripts/generate-political-intelligence.ts && npx tsx scripts/generate-rss.ts && npx tsx scripts/generate-sitemap.ts",
|
|
52
52
|
"build": "vite build",
|
|
53
53
|
"build:lib": "tsc -p tsconfig.lib.json && tsc -p tsconfig.npm-scripts.json",
|
|
54
54
|
"postbuild": "cp rss.xml dist/rss.xml && cp sitemap.xml dist/sitemap.xml && cp -r cia-data dist/cia-data",
|
|
@@ -70,7 +70,9 @@
|
|
|
70
70
|
"validate-translations": "npx tsx scripts/validate-translations.ts",
|
|
71
71
|
"validate-news": "node scripts/validate-news-translations.ts",
|
|
72
72
|
"validate-all": "npm run htmlhint && npm run validate-translations && npm run validate-news",
|
|
73
|
-
"generate-news": "
|
|
73
|
+
"generate-news": "npx tsx scripts/render-articles.ts --all --lang en,sv",
|
|
74
|
+
"aggregate-analysis": "npx tsx scripts/aggregate-analysis.ts --all",
|
|
75
|
+
"render-articles": "npx tsx scripts/render-articles.ts --all --lang en,sv",
|
|
74
76
|
"generate-news-indexes": "node scripts/generate-news-indexes.ts",
|
|
75
77
|
"generate-sitemap": "node scripts/generate-sitemap.ts",
|
|
76
78
|
"generate-sitemap-html": "npx tsx scripts/generate-sitemap-html.ts",
|
|
@@ -163,13 +165,14 @@
|
|
|
163
165
|
"@types/papaparse": "5.5.2",
|
|
164
166
|
"@vitest/coverage-v8": "4.1.5",
|
|
165
167
|
"@vitest/ui": "4.1.5",
|
|
166
|
-
"ajv": "8.
|
|
168
|
+
"ajv": "8.20.0",
|
|
167
169
|
"ajv-formats": "3.0.1",
|
|
168
170
|
"chart.js": "4.5.1",
|
|
169
171
|
"chartjs-plugin-annotation": "3.1.0",
|
|
170
172
|
"d3": "7.9.0",
|
|
171
173
|
"eslint": "10.2.1",
|
|
172
174
|
"globals": "17.5.0",
|
|
175
|
+
"gray-matter": "^4.0.3",
|
|
173
176
|
"happy-dom": "20.9.0",
|
|
174
177
|
"htmlhint": "1.9.2",
|
|
175
178
|
"js-yaml": "4.1.1",
|
|
@@ -177,14 +180,23 @@
|
|
|
177
180
|
"knip": "6.6.2",
|
|
178
181
|
"papaparse": "5.5.3",
|
|
179
182
|
"playwright": "1.59.1",
|
|
183
|
+
"rehype-autolink-headings": "^7.1.0",
|
|
184
|
+
"rehype-raw": "^7.0.0",
|
|
185
|
+
"rehype-sanitize": "^6.0.0",
|
|
186
|
+
"rehype-slug": "^6.0.0",
|
|
187
|
+
"rehype-stringify": "^10.0.1",
|
|
188
|
+
"remark-gfm": "^4.0.1",
|
|
189
|
+
"remark-parse": "^11.0.0",
|
|
190
|
+
"remark-rehype": "^11.1.2",
|
|
180
191
|
"start-server-and-test": "3.0.2",
|
|
181
192
|
"tsx": "4.21.0",
|
|
182
193
|
"typedoc": "0.28.19",
|
|
183
194
|
"typedoc-plugin-mdn-links": "5.1.1",
|
|
184
195
|
"typescript": "6.0.3",
|
|
185
196
|
"typescript-eslint": "8.59.0",
|
|
197
|
+
"unified": "^11.0.5",
|
|
186
198
|
"vite": "8.0.10",
|
|
187
|
-
"vite-plugin-sri-gen": "1.
|
|
199
|
+
"vite-plugin-sri-gen": "1.4.0",
|
|
188
200
|
"vitest": "4.1.5",
|
|
189
201
|
"worldbank-mcp": "1.0.1"
|
|
190
202
|
},
|