The admin surface is Microsoft Lists — no separate admin app to deploy.
Fastest setup — entirely inside the add-in, no IDs to find:
Repeat step 3 per division. Requires edit rights on the site.
document the schemas for admins who prefer to create or audit everything manually
in Microsoft Lists (both paths produce identical lists).
On your chosen SharePoint site, create a list named LegislativeRoutingMatrix
with these columns (all "Single line of text" unless noted):
| Column | Notes |
|---|---|
| Title | = DivisionCode (SharePoint's built-in Title column) |
| DivisionCode | MVD, TDD, SOD, ELT, AG Office, … |
| DivisionName | Motor Vehicle Division, … |
| Aliases | semicolon-separated alternative names ("Motor Vehicle; Motor Vehicles") |
| Emails | semicolon-separated targeted-email recipients |
| TeamsTeamId | Teams team GUID (Teams → team → ⋯ → Get link to team → groupId=) |
| TeamsChannelId | channel ID (⋯ on the channel → Get link to channel → 19:...@thread.tacv2) |
| TeamsChannelName | display name (for the review UI) |
| TeamsTagId | tag GUID — use the add-in's Settings → "Teams tag ID lookup" |
| TeamsTagName | tag display name as it appears in Teams |
| CodeChapters | semicolon-separated Iowa Code chapters this division owns ("321; 321A; 322") — powers division SUGGESTIONS for unrouted bills (optional) |
| MentionUserIds | semicolon-separated Entra object IDs (optional, for individual mentions) |
| MentionUserEmails | matching display emails (optional) |
| IsActive | Yes/No |
| Priority | Number — highest wins when multiple rules match a division |
| EffectiveStartDate | Date (optional) |
| EffectiveEndDate | Date (optional) |
| Notes | free text |
Rule semantics: a division token from the report matches a rule when it
equals the DivisionCode, DivisionName, or any alias (case-insensitive). Among
matches that are active and within their effective dates, the highest
Priority wins. Session handoffs = add the new rule with a later
EffectiveStartDate and end-date the old one; history stays intact.
Same site, list named LegislativeAudit, columns (Single line of text):
Title (bill number) ReportKey IdempotencyKey TeamId ChannelId
TeamsMessageId Status Error Divisions EmailRecipients
PublishedBy SourceSubject
The add-in appends one row per publish attempt. Do not delete rows for
reports that may be re-run — the IdempotencyKey rows are what prevent
duplicate posts.
Same site, list named BillTracker — this is the shared "who's waiting on
who" board and replaces individual completeness spreadsheets. Columns:
| Column | Type | Notes |
|---|---|---|
| Title | text | bill number (written by the add-in) |
| Division | text | one row per bill × division |
| Status | Choice | Pending review / In review / Commented / No comment needed |
| DueDate | Date | auto-set to +2 business days at publish |
| BillLink | text | BillBook URL |
| Brief | text | first 250 chars |
| ReportKey | text | which report published it |
The add-in writes one Pending review row per bill × division at publish
time; division staff update Status themselves.
Pin it in Teams: in the legislative channel, **+ Add a tab → Lists →
existing list → BillTracker**. Create these views:
Fill-in files showing exactly what each list expects:
Microsoft Lists imports Excel directly: List → ⋯ → "Export/Import" or create
the list *from* the Excel file, then rename columns to match the table
above. For tag IDs, use the add-in's tag lookup (Settings → paste the Team
ID → Fetch tags) and copy each TeamsTagId into the matching row.
docs/permissions.md).In the add-in: Settings → connect the site → parse a test report → the
Review screen shows exactly which rule each division resolved to and flags
rules missing tag IDs. Preview shows the rendered post before anything is
published.
The add-in is state-configurable:
states.json in the repository and set the OPENSTATES_API_KEY repository secret (free key from openstates.org). The scheduled mirror then publishes feeds/openstates-<state>.json automatically.Bill briefs reference the Iowa Code ("Amends Code Chapter 9", "Code
chapters 6A and 6B"). The add-in extracts these references and:
CodeChapters column.The tracked list ships seeded from the DOT's 2015 tracking list
(Settings → "Tracked Code chapters") and is FULLY EDITABLE — the 2015
list predates several Code changes, so review it with your legislative
coordinator and paste the updated set. It travels with org profiles.
The Router can compose the daily report itself:
The generated report's text round-trips through the Router's own parser,
so recipient agencies running their own Router can parse it directly.