← All white papersBuild plan · September 2026

The Rejected Pack on Microsoft 365

One graph where each fact lives once, obligations that carry their citation, and a pack generated from bound records rather than assembled in a folder.

12 min read·Free to implement·Published by AI Pathway

Used by

  • Business Systems Analyst
  • HSEQ Administrator
  • Document Controller
  • Compliance Officer

This is the parent standard, and it is the one with the most to lose from a casual implementation. Every business already has a version of this: a folder per client, per site, per job, full of documents that were correct when somebody put them there. The standard replaces the folder with a graph and a generator, and the tenant is a perfectly good place to put both.

In short

  • What this is

    A build plan for the rejected pack standard on Microsoft 365. Six lists, two libraries, four flows, six measures.

  • The core rule

    Change the trading address once and every pack generated afterwards is right. That property is what you are building, and a copied value destroys it.

  • What it does not do

    It assembles a complete, current, evidenced pack and puts it in front of the person who releases it. It does not certify anything and it does not decide that an obligation is satisfied.

  • The hard part

    The binding layer. The standard names it as the step not to hand-roll, and there is no product for it, so this is where the care goes.

Take the spec to Claude, ChatGPT or Copilot. The sentence to paste is one click away.

Want the whole thing by email?

This paper, plus the rest of the library. One click to stop them.

1. Before you start

Read the rejected pack build standard first, and its operator runbook if people rather than systems are your constraint. Shared conventions for this stack are in building the standards on Microsoft 365.

One thing to be clear about before anyone starts building. The standard names the binding layer as the step not to hand-roll, and unlike some of the others there is no product for it. That is not an oversight and this page will not pretend otherwise. It means the binding step deserves the most care, the most testing, and the refusal behaviour built first.

2. The lists, with their columns

Six lists and two libraries. The shape looks heavier than the others because it is a graph, and the weight is the point: it is what lets one edit re-derive everything downstream.

For your developer. Show the fields
Site: Packs

LIST  Entity                (usually one row. Sometimes a few.)
  ABN             Text            indexed
  LegalName       Text
  TradingName     Text
  TradingAddress  Text            CHANGE IT HERE. Nothing copies it.

LIST  Locations
  Entity          Text            indexed. lookup to Entity

LIST  People
  Entity          Text            indexed. lookup to Entity
  Role            Text

LIST  Tickets
  Person          Text            lookup to People
  Class           Choice          licence | white_card | high_risk | induction
                                  | visa
  Number          Text
  ExpiresOn       DateTime        indexed
  Evidence        Hyperlink       into the Evidence library

LIST  Cover                 (insurance)
  Entity          Text            lookup to Entity
  Type            Choice          workers_comp | public_liability | vehicle
  Insurer         Text
  PolicyNo        Text
  ExpiresOn       DateTime        indexed
  Evidence        Hyperlink

LIST  Obligations
  ObligationId    Text            indexed
  Trigger         Text            what makes this apply here
  Citation        Text            REQUIRED. The rule that says so.
  Artifact        Text            what has to exist as a result
  Cadence         Text
  PenaltyClass    Choice          your regulator's own classes
  EffectiveFrom   DateTime
  Applicability   Choice          applies | does_not_apply
  WhyNot          Text            REQUIRED when does_not_apply
  Location        Text            lookup to Locations

LIBRARY  Evidence           (the documents, with what they evidence)
  BoundTo         Text            indexed, REQUIRED. What it evidences.

LIBRARY  Packs              (generated output only. Never hand-edited.)
  Pack            Text            indexed. The id PackArtifacts points at.

LIST  PackArtifacts
  Pack            Text            indexed
  Obligation      Text            lookup to Obligations
  Version         Text
  GeneratedAt     DateTime
  AsOf            DateTime        the facts as at this moment
  Sources         Text            which rows produced it
  Bound           Boolean         false blocks the pack

PackArtifacts is what makes a pack regenerable and auditable. Without it you have a PDF and a hope, and the question you cannot answer six months later is which version of which fact it carried.

3. Every check, and what enforces it

The checkEnforced byHow
A fact lives in one place and everything re-derivesLookupsThe trading address is a column on Entity and a lookup everywhere else. Changing it once changes every pack generated afterwards, which is the whole argument of the standard.
An obligation carries the rule that says soList designCitation is required. An obligation with no citation cannot be defended when somebody asks why the artifact exists, and it is usually the one that turns out not to apply.
Does not apply is a written reason, not an absenceList designApplicability plus WhyNot, both required when it does not apply. A silently missing obligation looks identical to one nobody thought of.
Evidence binds to the thing before the pack can closePack flowThe generate step refuses while any required artifact is unbound. This is the binding layer and it is the step the standard names as the hard one.
The pack is generated, never assembled by handPack flowArtifacts carry version, generated_at, as_of and their sources. A pack somebody built in a folder has none of those and cannot be regenerated.
A named person is on the gateApprovalThe pack is released by a person from a named group, recorded on the pack, not by whoever happened to run the flow.
Expiry is derived and surfaces before it bitesExpiry flowTickets, insurance and inspections all carry ExpiresOn, and the flow moves the pack out of current before the date rather than after somebody is refused on site.

4. The four flows

For your developer. Show the fields
FLOW 1  Bind evidence
  trigger  a file lands in the Evidence library
  logic    require the obligation or ticket it evidences before
           the upload can complete
           set Bound on the matching PackArtifacts row
  never    accept a document with nothing named. An unattached
           file in a library is the folder problem with extra steps.

FLOW 2  Generate the pack
  trigger  requested, or scheduled per location
  guard    REFUSE while any required artifact has Bound = false.
           Write what is missing, and stop. This is the binding
           layer, and a warning here is a failed implementation.
  logic    render each artifact from the graph, by lookup
           stamp Version, GeneratedAt, AsOf and Sources
           write the output to the Packs library
  never    read a copied value. Everything resolves through Entity.

FLOW 3  Release
  trigger  a generated pack awaiting release
  logic    request approval from the named group
           record the approver on the pack
  never    release on behalf of whoever ran the generate

FLOW 4  Expiry
  trigger  scheduled, daily
  logic    Tickets and Cover with ExpiresOn inside the lead time
           -> mark dependent packs not current, notify the owner
           past ExpiresOn -> packs are not current, full stop
  note     run this against the graph on a clock, not at handover.
           At handover, somebody is already standing at a gate.

Flow 2's guard is the one sentence of this page that matters most. Everything else is plumbing around a refusal.

5. The Power BI model and its measures

For your developer. Show the fields
Unbound Artifacts =
CALCULATE ( COUNTROWS ( PackArtifacts ), PackArtifacts[Bound] = FALSE )

Packs Blocked =
CALCULATE (
    DISTINCTCOUNT ( PackArtifacts[Pack] ),
    PackArtifacts[Bound] = FALSE
)

Expiring 30 =
CALCULATE (
    COUNTROWS ( Tickets ),
    Tickets[ExpiresOn] <= TODAY () + 30,
    Tickets[ExpiresOn] >= TODAY ()
)

Expired Live =
CALCULATE ( COUNTROWS ( Tickets ), Tickets[ExpiresOn] < TODAY () )

Obligations Without Citation =          -- must be zero
CALCULATE ( COUNTROWS ( Obligations ), ISBLANK ( Obligations[Citation] ) )

Does Not Apply Without Reason =         -- must be zero
CALCULATE (
    COUNTROWS ( Obligations ),
    Obligations[Applicability] = "does_not_apply",
    ISBLANK ( Obligations[WhyNot] )
)

Pack Age Days =
AVERAGEX ( PackArtifacts, DATEDIFF ( PackArtifacts[AsOf], NOW (), DAY ) )

The two must-be-zero measures are the cheapest audit in this library. An obligation with no citation and a does-not-apply with no reason are both the same failure: somebody decided something and left no way to check it.

6. The order to build it in

  1. Build Entity, Locations and People first, with one row each. The graph before anything that reads it.
  2. Add Tickets and Cover. Index ExpiresOn now.
  3. Load Obligations for one location, with at least one marked does not apply so the WhyNot requirement is exercised.
  4. Build Flow 1 and confirm a file cannot be uploaded without naming what it evidences.
  5. Build Flow 2 with the refusal first, before any rendering. Prove it refuses, then teach it to generate.
  6. Run the pass test: change the trading address and regenerate.
  7. Build Flow 3, then Flow 4.
  8. Connect Power BI. The two must-be-zero measures go on the front page.

7. Four traps specific to this build

A pack as a folder of PDFs

This is what everybody already has and it is precisely what the standard replaces. A folder cannot tell you which version of a fact each document carries, cannot be regenerated after the address changes, and quietly becomes stale one document at a time.

Re-typing the entity details onto each pack

The moment a fact exists in two places, one of them is wrong and it is usually the one that went out. Everything that names the entity is a lookup, and the pack template reads the lookup rather than a copied value.

Treating unbound as a warning

If the generate step runs and posts a note about missing evidence, packs go out incomplete and the note is the thing nobody reads. Unbound must stop the generate. That is the difference between this standard and a checklist.

Expiry checked when the pack is requested

By then it is too late: somebody is at a gate. Run expiry on a schedule against the graph, and let the pack's currency be a property of the facts rather than a question asked at handover.

8. Where the automation stops

  • Certifying anything, or signing on behalf of a licensed person.
  • Deciding that an obligation does not apply. A flow can require the reason; it cannot supply it.
  • Releasing a pack. A named person from a named group, recorded.
  • Deciding an expired ticket is close enough to let somebody on site.
  • The binding layer's judgement calls. There is no product for this step and nothing here pretends there is.

The pass test. Two checks, both on test data. First, mark one required artifact unbound and request a pack: the generate must refuse and name what is missing, and no file may appear in the Packs library. Second, change TradingAddress on Entity and regenerate a pack that was correct before: the new pack must carry the new address without anyone editing a template, and the old pack must still show the old one with its own AsOf. If the first produces a pack with a warning attached, you have built a checklist. If the second needs a template edited, a fact lives in two places and you have not built the graph the standard is about.

Related reading