Template:POFMA-direction-cargo

Revision as of 10:02, 19 July 2026 by SGPolitico (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

This template defines the table "pofma_directions". View table.

Design reference for the {{POFMA-direction-cargo}} template and its backing Cargo table `pofma_directions`. This replaces the flat `{| class="wikitable sortable"` table previously used on POFMA directions. Follows the no-Lua, declare/store pattern documented in `politicalsg-wiki-structure.md` §§2–3.

Why this needed a Cargo redesign

The flat wikitable on the live POFMA page stores nothing queryable: it cannot be filtered by ministry, cross-referenced against an MP's appointment history, or linked to the multiple simultaneous directions that often accompany a single underlying falsehood (e.g. the four directions issued together on 22 January 2020 over the Changi Prison execution-method allegations). The source spreadsheet this schema is drawn from already tracks the data relationally — a directions table, a ministers roll-up, a targeted-entities roll-up, and a topics roll-up — which is exactly what Cargo is for.

Naming convention

`direction_id` is `pofma-{issue_date}-{target-slug}`, with a trailing `-2`, `-3`, etc. appended where the same ministry issues more than one direction to the same target on the same date (e.g. the three separate December 2019 directions to the Singapore Democratic Party, each over a different post). This follows the existing Change ID convention (entity-id + type + year) in `politicalsg-template-reference.md`, adapted since a direction's "entity" is really the recipient, not a single evolving record.

`incident_id` is a second, optional slug that groups multiple `direction_id` records issued over the same underlying falsehood, regardless of date or recipient — e.g. `changi-prison-execution-allegations-2020` links the four 22 January 2020 directions to Lawyers for Liberty, Kirsten Han, The Online Citizen, and Yahoo Singapore. This is the same "design for shared linkage from the outset" principle already applied to Hansard/case-law tables — retrofitting it later would mean re-touching every existing record.

Field reference

Field Type Required Notes
direction_id slug Yes Permanent. `pofma-{issue_date}-{target-slug}`, e.g. `pofma-2019-11-13-brad-bowyer`. Never changed once set.
incident_id slug No Groups directions over the same underlying falsehood. Leave blank for a standalone direction.
direction_type enum Yes `Correction Direction` / `Targeted Correction Direction` / `General Correction Direction` / `Disabling Order` / `Access Blocking Order` / `Declared Online Location` / `Conditional Warning`. See §Schema limits for the "Media Statement" edge case.
issue_date YYYY-MM-DD Yes Date the direction itself was issued.
post_date YYYY-MM-DD No First date of the target post/material. Blank where not applicable (e.g. platform-directed TCDs, ISP-directed ABOs).
days_between integer as string No Days between `post_date` and `issue_date`. Carried over from the source spreadsheet rather than computed, since some rows have no `post_date` to compute from.
ministry_id ministry slug Yes Must match the `ministries` table, e.g. `mha`, `mom`, `moh`. See §Ministry slugs below for disambiguation.
issuing_minister mp_id slug No Blank when `alternate_authority=yes`.
alternate_authority enum Yes `yes` / `no`. `yes` during election periods when a senior official, not the Minister, is authorised to act (see s52 POFMA).
target_name text Yes Display name of the individual, entity, party, platform, or ISP category targeted.
target_id slug No Cross-reference to an `entity_id`, `party_id`, or `mp_id` if a wiki page exists for the target. Leave blank otherwise — do not invent a slug for a person with no page.
target_type enum Yes `Individual` / `Media Entity` / `Political Party` / `Platform` / `Internet Service Provider`.
platform text No Where the targeted material was communicated, e.g. `Facebook`, `Website`. Distinct from `target_name`: a Targeted Correction Direction's target IS the platform (e.g. `target_name=Facebook`, `platform=Facebook`), whereas an ordinary Correction Direction's target is a person or entity whose post appeared ON a platform (e.g. `target_name=Brad Bowyer`, `platform=Facebook`).
subject_summary text Yes One-line factual description of the underlying falsehood. Editorial precis, not a verbatim quotation of the press release.
topic_tags text No Comma-separated, e.g. `COVID-19, Legal enforcement`. Matches the "Key subject" roll-up in the source spreadsheet.
source_pdf text No Filename of the POFMA Office press-release PDF, where known.
source_url URL No Direct link to the direction or press release, where publicly available.
verified enum Yes `yes` / `no`.
last_updated YYYY-MM-DD Yes Date of data entry, not the direction's issue date.

Ministry slugs used in this table

`mof` = Ministry of Finance; `mfa` = Ministry of Foreign Affairs; `mha` = Ministry of Home Affairs; `mom` = Ministry of Manpower; `moe` = Ministry of Education; `mci` = Ministry of Communications and Information (renamed MDDI in 2023 — see the ministry_changes table for that record; `ministry_id` stays `mci` per the permanent-ID rule); `moh` = Ministry of Health; `mti` = Ministry of Trade and Industry; `mnd` = Ministry of National Development; `mlaw` = Ministry of Law; `msf` = Ministry of Social and Family Development; `mot` = Ministry of Transport; `pmo` = Prime Minister's Office. Note `mof` (Finance) vs `mfa` (Foreign Affairs) is a deliberate disambiguation from the existing `mfa` example in `politicalsg-template-reference.md` — do not confuse the two.

The People's Association issued directions directly in March 2020 (before the Alternate Authority provisions were relied on more generally); it is a statutory board, not a ministry, so has no `ministries` table entry. Until an `entities` record exists for it, leave `ministry_id` blank for those rows and note the issuing body in `subject_summary` instead of forcing it into a field it doesn't fit.

Schema limits found while designing this table

Recorded here so they aren't rediscovered, per the wiki's stress-test-before-finalising convention:

  • Not every row in the source spreadsheet is a "direction". At least one row (30 January 2020, Ministry of Communications and Information) records a media statement lifting exemptions on several platforms — an administrative act, not a Part 3/4/5 direction. Do not force this into `direction_type`; such rows should either get a `Media Statement` value added to the enum in a future schema revision, or be kept out of this table entirely and handled in prose. This page's worked examples on POFMA directions omit that row pending a decision.
  • "Platform" and "target" collide in meaning for some direction types. A Targeted Correction Direction's `target_name` and `platform` are usually identical (both "Facebook", say); an ordinary Correction Direction's are usually different. This is intentional, not an error — see the field reference above — but it means a naive `#cargo_query` grouping by `platform` alone will mix "directions issued to a platform" with "directions about a post that happened to appear on that platform". Query authors should filter on `direction_type` as well.
  • Multiple directions, one incident. Roughly a fifth of directions in the source data share a `subject_summary` with at least one other direction issued the same week. The `incident_id` field exists to make these queryable as a group; it has not yet been back-filled for the full historical dataset (see §Outstanding work).

Outstanding work

  • Back-fill `incident_id` for directions clustered around the same underlying falsehood — done for the Changi Prison cluster on POFMA directions as a worked example; the remainder of the historical dataset is not yet converted.
  • Decide whether to add `Media Statement` (or a broader `Administrative Notice` category) to the `direction_type` enum, or keep this table strictly to Part 3/4/5 directions and cover administrative acts like exemption-lifting in prose on the main POFMA directions page instead.
  • A Python conversion script (matching the pattern already used for the Hansard workflow) would speed up the remaining bulk entry from the source spreadsheet; not yet written for this table.