Review the Posting Register
The Posting Register is a tenant-level console, outside any single project, where finance and accounting review ERP postings across every project and connection they’re permitted to see. Where ERP Post History is scoped to one project you already have access to, the Posting Register is the cross-project view built for a reviewer who needs to see postings from many projects and connections in one place.
The Posting Register is built for review first. Two bulk actions — clearing simulated postings and retrying failed ones — let you act directly from the grid, AI Assist helps you find and understand postings faster, and Trends, Lineage, and Export let you analyze, drill back to source, and get data out. Reversal exists as an API capability (see Reversal), but nothing in the console itself changes, reverses, or approves a posting yet.
Who Can Open It
Section titled “Who Can Open It”Opening the Posting Register takes one of four built-in security groups, seeded from four Keycloak realm scopes. Each tier is cumulative — holding a higher tier includes everything the tiers below it grant:
| Scope | Grants |
|---|---|
erp.register.view |
Open the register and review postings, including Trends and Lineage. |
erp.register.operate |
Everything .view grants, plus bulk actions, initiating a reversal, and exporting or scheduling a delivery. |
erp.register.approve |
Everything .operate grants, plus resolving a stuck reversal attempt. |
erp.register.admin |
Everything .approve grants, plus the auditor export profile (unmasked money and maker identity) and setting the tenant’s retention policy. |
The Visibility Rule
Section titled “The Visibility Rule”Holding an erp.register.* scope opens the console, but it doesn’t by itself make any posting visible. A posting is visible in the register only if you also hold a personal connection grant on that posting’s connection, and — when the posting belongs to a project — access to that project. A posting that isn’t tied to a project is gated by the connection grant alone.
This is a separate grant from the register scope above, and both are required:
- Connection grant. You need to be an explicit owner of the connection, or named individually, or a member of a security group named on it — the same grants a connection’s Security Model controls. A connection set to
All Workspace Membersdoes not grant register visibility. That setting makes the connection usable by everyone; it isn’t a personal, group, or ownership grant, and the register requires one of those specifically. - Project access, for any posting that belongs to a project — the same access your other project work requires.
A member who holds erp.register.view but no connection grants at all sees a correctly empty register, and the console tells them so rather than looking broken. A connection or project grant that’s revoked takes effect on your next page load — there’s no stale visibility to clear.
The Exception Queue
Section titled “The Exception Queue”Opening the register lands you on the Exception Queue, not the grid — the postings most likely to need your attention, grouped into four buckets and shown in priority order:
- In Doubt — the post was submitted and nothing yet confirms what became of it.
- Unconfirmed — submitted, and past the deadline it should have confirmed by.
- Pending — an asynchronous post, past the deadline it should have resolved by.
- Failed — rejected by the ERP.
“Aged” is measured against the platform’s own timers, not an invented threshold, so a posting lands in a bucket exactly when the platform itself would call it overdue. Within each bucket, the oldest postings come first.
Simulated postings never appear in the queue or its counts — the queue states how many were excluded, so a low count is never mistaken for “nothing to review” when simulations are the reason. Filtering to one bucket narrows the rows shown; it doesn’t change what the other buckets’ counts say, so switching to Failed never makes In Doubt look empty.
The same visibility rule as the grid applies here: you only see exceptions on postings tied to a connection you’re personally granted, in a project you can access.
Connection Health
Section titled “Connection Health”A banner above the Exception Queue and the roll-up views (below) answers a question neither of them does on its own: is one of your connections down? For every connection you’re personally granted — and only those — it shows the last successful post and whether that connection is currently erroring. A granted connection with no postings yet says so rather than being left off the list, and if the health check itself can’t be completed, the banner says that too rather than quietly reporting all clear.
The Register Grid
Section titled “The Register Grid”Switch to the grid to see every posting rather than only the exceptions — it lists postings across every project and connection you can see, one row per posting. Filter on:
- Project
- Environment
- Connection
- ERP type
- Entity
- Posting date
- State
Bulk Actions
Section titled “Bulk Actions”From the grid, select more than one posting and act on all of them together. Select postings by ticking their rows, or by choosing select all matching the current filter — which reaches every posting the filter matches across every page, not just the ones already loaded.
Two actions are offered:
- Clear simulated postings — a soft delete for simulated postings you no longer need to keep around.
- Retry failed postings — resend postings the ERP rejected, or that were never sent.
The Impact Preview
Section titled “The Impact Preview”Before either action runs, PlaidCloud shows an impact preview: how many postings are affected, the money involved (broken out by currency — amounts are never blended across currencies, and an uncaptured amount shows blank, never 0.00), and which connections and entities the affected postings belong to. Anything in your selection the action can’t touch is called out separately, so “24 of your 30 selected postings will do nothing” is visible before you commit, not discovered after.
Type-to-Confirm
Section titled “Type-to-Confirm”Above a threshold, Apply stays disabled until you type the affected amount to match it exactly.
Retry Only Runs Against What You Checked
Section titled “Retry Only Runs Against What You Checked”Clearing simulated postings can run against either kind of selection — ticked rows or everything matching your filter. Retrying can’t: it only ever runs against postings you’ve individually ticked. A filter-wide selection has no fixed list of postings to hold the retry to, so retrying asks you to paste the postings back in, and refuses to proceed unless what you paste is exactly what the preview showed — the same postings, no duplicates, and the same count. That binding is what keeps the confirmation honest: the batch you confirmed is the batch that gets sent.
What Can Be Retried
Section titled “What Can Be Retried”Only a posting the ERP rejected, or one that was never sent, can be retried. One still in flight, in doubt, or already posted can’t be retried from here.
Where the connection’s ERP supports it, PlaidCloud asks the ERP directly before retrying: if the ERP already holds the document as posted, the retry is refused and reversal is suggested instead. If the ERP can’t answer that check, the retry is refused rather than risked — it never guesses. A few connections don’t support this check at all; for those, the retry relies on the posting’s own recorded rejection.
Retrying requires erp.register.operate and your own personal grant on that posting’s connection — the same connection grant The Visibility Rule requires to see the posting at all.
Clearing Simulated Postings
Section titled “Clearing Simulated Postings”Clearing is a soft delete: PlaidCloud records who cleared it and when, and requires a reason before Apply is enabled. It removes the postings from the simulate preview store and the ledger’s own simulate journal — it never touches a live posting, and there’s no way to point it at one.
AI Assist
Section titled “AI Assist”Assist opens a search box, a row of proactive cards, and a per-row advice panel — every figure on it is computed by the register itself, over your own live grants; the model, where one is configured, only explains or drafts, and never invents a number or a predicate.
Ask in Plain Words
Section titled “Ask in Plain Words”Type a sentence — “postings in doubt for the EMEA connection last week” — and it’s parsed into the register’s own filter vocabulary by a fixed table, not a model call: a parse can only ever narrow the rows the grid would already show you, never reach a row you weren’t granted. The model’s only role is to explain the parse in a sentence: it names the field it matched and how many of your rows the resulting filter finds.
Proactive Cards
Section titled “Proactive Cards”Seven cards summarize what’s worth a look, each with a live count and sample rows scoped to your own grants: outstanding to close, near-duplicates, the intercompany net-zero gap, changed vs. last close, confirmed in ERP, aging & owners, and already reversed. A short narrative sentence sits beside the figures where an LLM connection is configured for your workspace; where none is, the card still renders in full and says why the narrative is missing. An uncaptured amount on a card is always blank, never 0.00 — the same rule the roll-up views follow.
Per-Row Advice
Section titled “Per-Row Advice”Pick a posting and get two kinds of advice, depending on its state:
- A reversal draft, for any posting — what reversing it would look like: whether the connection’s driver supports it at all, the control-total it would need to tie to, and a period check. It is a draft only; nothing here reverses anything.
- Failure direction, for a rejected or in-doubt posting — why it failed, whether to retry it or fix the source data first, which field to fix, and the duplicate risk of pressing retry. The ERP’s own error message is free text, so it’s classified into a cause server-side rather than shown to you directly — the same rule that keeps free text out of the rest of the register.
The Daily Digest
Section titled “The Daily Digest”A digest previews, on demand, the cards above scoped to a close-relevant subset — outstanding-to-close, aging & owners, near-duplicates, the IC net-zero gap, and confirmed-in-ERP — as they’d appear if sent to you today. A toggle subscribes or unsubscribes you; the subscription stores nothing but your member id, so a grant you lose afterward simply drops those rows out of your next digest rather than leaking a stale view.
Reversal
Section titled “Reversal”Reversing a posting — creating a new, opposite document in the ERP — is a real, shipped capability, but it’s reachable through the API only; the console has no Reverse button or reversal dialog yet.
- Eligibility depends on the posting’s own state (only a posted entry with a confirmed ERP document id can be reversed), the connection’s driver (some, like Oracle Fusion, support no programmatic reversal at all), and whether a reversal attempt is already outstanding on it.
- Reversing can optionally redirect the new entry to a different target period than the original posting — honored on adapters whose ERP accepts an explicit posting period, refused with a clear error on ones that can’t aim it. A hard database latch stops a second reversal attempt from ever being dispatched while one is outstanding, even across a process crash mid-dispatch; an ERP rejection releases that latch automatically, since nothing was created.
- A reversal left
pendingorin_doubt— its outcome unknown — doesn’t resolve itself; v1 has no automated reverse-confirmation, by design. It’s cleared by a human holdingerp.register.approve, who checks the ERP directly and records what they found:released(nothing was created there, so the posting becomes reversible again) orconfirmed(a reversing document exists, with its id) — which is the only way that latch is ever cleared.
Segregation of duties isn’t enforced on any of this yet: a reversal records who approved it, but nothing currently requires a second person to have done so.
Trends
Section titled “Trends”Trends shows failure rate and latency, grouped by connection or ERP type, plus the reversal reason-code distribution — every figure, including every denominator, computed over your own live grants. A connection with nothing terminal in the window shows an em dash for its failure rate, never 0%, since a perfect zero would put a connection nobody uses at the top of a health list. Latency is a bounded sample over the most recent terminal postings, labeled as a sample rather than presented as if it covered the whole window. Reversal reasons appear as their structured codes only — the free-text reason a person typed is never bucketed or shown here.
Lineage
Section titled “Lineage”Lineage drills from one posting back to the workflow run that produced it, and out to the document in the ERP itself. Look it up by run id or by a posting’s ledger id — asking by ledger id resolves the run through your own grants first, so a posting on a connection you can’t see resolves nothing rather than exposing which run it came from. Where PlaidCloud can verify the ERP’s document URL shape for that adapter, lineage includes a deep link straight to the document; where it can’t, or the posting was never confirmed, it says which of those is why rather than guessing at a link. The ERP’s business key still never appears here — the lineage key is the workflow’s run_id, and the ERP pointer is confirmation_id, the same as everywhere else in the register.
Export
Section titled “Export”Exports & Alerts is where the register leaves the console as a file or a notification — and the one surface where PlaidCloud’s controls stop applying the moment the bytes leave. Producing an export or scheduling a delivery requires erp.register.operate; opening the register to look at it does not.
Downloading Now
Section titled “Downloading Now”Export the register you’re currently looking at as an Excel-friendly CSV or as JSON, built fresh under your own live grants. Two masking profiles apply depending on your role:
erp.register.operategets the standard, masked profile: money and maker identity are withheld.erp.register.admingets the auditor profile — the only one that carries money and maker identity unmasked.
Every export follows the same rules as the rest of the register: natural_key never appears, free-text fields (comments, dimension and worktag values) are excluded outright rather than merely scrubbed, and an uncaptured amount is blank — distinguished from a masked one, so a blank never reads as “nothing was posted” when it actually means “your role doesn’t see this.”
Scheduling a Delivery
Section titled “Scheduling a Delivery”Create a schedule — a filter, a cadence, a format, and a list of recipients by member, or a Slack connection for a notification with no row content at all. Two kinds are offered:
- Export — a recurring CSV or JSON delivery of the filtered register.
- Alert — a notification triggered by one of three conditions: a failed live post, an aging authorization, or a posting reversal. Preview what a trigger would currently match for you before subscribing to it.
Each recipient’s file is built from their own live grants at the moment of sending, not the schedule owner’s — two recipients on the same schedule can receive two different files, and a recipient who has since lost the export role, lost every connection grant, been disabled, or has no address on file is skipped individually with a stated reason rather than silently dropped. Only the schedule’s owner or an erp.register.admin can delete or fire someone else’s schedule.
Retention
Section titled “Retention”Configure how long the register keeps three kinds of history: captured payload detail, simulated postings, and the audit trail — each as a day count, tenant-wide, requiring erp.register.admin. Every field is written on every call; an omitted field clears that horizon rather than leaving it unchanged, and an unconfigured tenant keeps everything (every horizon reads as null, not a hidden default).
Like scheduled delivery, the retention sweep that acts on this policy has no periodic invoker yet — it runs only when explicitly called, for the same reason: PlaidCloud has no scheduler to hang it off yet.
Roll-Up Views
Section titled “Roll-Up Views”Group the register by run, period, or connection to see subtotals and a status roll-up instead of individual rows, reachable from the register alongside the grid and the exception queue.
- Blank money stays blank. A posting with no captured amount — every SAP posting, a born-terminal posting, or one written before this feature existed — contributes nothing to a subtotal and is never shown as
0.00. Each group states in words whether every posting in it was captured, some weren’t, or none were. - Currencies are never mixed into one total. PlaidCloud does no foreign-exchange conversion, so a group spanning more than one currency is broken out by currency rather than blended into a single misleading figure.
- A capped group list still totals correctly. If a grouping produces more groups than the view displays, the totals line still covers every group, not just the ones shown, and says so.
The Connection Health banner appears on this view too.
The Detail Drawer
Section titled “The Detail Drawer”Click a row to open its detail drawer. It’s organized into tabs:
| Tab | Shows |
|---|---|
| Request/Response | The outbound request and the ERP’s response, filtered for data minimization (see below). |
| Errors | Any error the ERP or the posting step returned. |
| Timeline | The posting’s states in order, from submission to its current state. |
| Related | The original posting and its reversal, linked to each other, when one exists. |
| Audit | A read-only record of activity on this posting. Sparse for now — see The Audit Tab below. |
Data Minimization
Section titled “Data Minimization”The register is built to show what a reviewer needs to confirm a posting happened, without surfacing the sensitive data a posting step handled to make it happen.
- Request and response payloads are allow-listed per adapter. A field only appears if it’s been explicitly classified as safe to keep. Bank account numbers, routing numbers, IBANs, tax ids, and other personal identifiers are stripped before you ever see the payload.
- The ERP business key is withheld entirely. It can embed a vendor name or another reference token, so it never reaches the register — including AI Assist: the same allow-list that decides what you see decides what a model prompt is allowed to see, and a natural-key value anywhere in that payload is refused outright rather than sent. Identify a row by its ledger id, and use the
confirmation_idas the ERP’s own pointer to the document — the same field ERP Post History callsconfirmation_id. - Free-text fields are pattern-scrubbed on read, and excluded outright — not just scrubbed — from the digest, any AI model prompt, and any export. Pattern-scrubbing catches a shape like an IBAN or a tax id; it can’t catch a vendor name typed into a memo, which is why anything leaving the console as a file drops those fields entirely rather than relying on the scrub alone.
The Audit Tab
Section titled “The Audit Tab”The Audit tab is display-only. Its detail is intentionally sparse in this release, because the underlying audit vocabulary hasn’t been classified yet — expect it to fill in as that work lands, not to change how you read the rest of the drawer.
What’s Not Here Yet
Section titled “What’s Not Here Yet”- No Reverse or Retry control on the detail drawer, or anywhere in the console UI. Retry is bulk-only (see Retry Only Runs Against What You Checked); reversal is API-only for now.
- No dedicated Reconcile or Control Totals screen. Control-total figures appear inline — in a reversal draft under AI Assist, and in the bulk impact preview — not as their own view.
- No approvals inbox and no segregation-of-duties enforcement. A reversal’s
approver_member_idis recorded but nothing currently requires it, or requires a second person’s sign-off. - No collaboration — no comments, @mentions, or review sign-off.
Everything else on this page — the exception queue, connection health, roll-up views, bulk actions, AI Assist, trends, lineage, and export — works today.