# The IncidentReports kit — confidential reports, their review, corrective actions and the people who must be told

> `Osysharp.IncidentReports` keeps incident reports — injuries, near misses, damage, concerns — readable by the person who filed them and by whoever reviews incidents, nobody else. The people involved with their injury, care and own statement; photos; a review with a severity, a cause, corrective actions with owners and due dates; the people who must be told (a child's guardians) and their acknowledgement; an authority's deadline on a durable clock; a register and its CSV.

<!-- id: ui-incident-reports-kit · area: ui · stability: preview · html: https://osysharp.com/reference/ui/incident-reports-kit/ -->

## Summary        {#summary}
`use Osysharp.IncidentReports@0;` keeps incident reports. The app says who reviews them:

```osy syntax
policy ReviewsIncidents => IsSafetyLead;   // reads every report, reviews, assigns actions, tells people, the register
policy ReportsIncidents => IsStaff;        // who may file one — anybody signed in, unless you narrow it
```

A report is then read by the person who filed it and by `ReviewsIncidents` — nobody else, in lists, counts and searches.

## Signature      {#signature}
```osy syntax
virtual policy ReviewsIncidents => false;        virtual policy ReportsIncidents => IsAuthenticated;
virtual policy ManagesIncidentSetup => ReviewsIncidents;
app.Incidents = new IncidentsSetup { AuthorityWarningHours = 24, CloseWithOpenActions = false, ReportersReadOutcome = true, Organisation = "" };
public interface IIncidentContacts { List<Principal> ContactsFor(Principal person); }

IncidentReport ReportIncident(IncidentCategory category, DateTime occurredAt, string location, string description,
                              string immediateAction = "", IncidentSeverity? severity = null);
IncidentPerson AddIncidentPerson(IncidentReport report, IncidentRole role, Principal? person = null, string name = "",
                                 string injury = "", IncidentTreatment treatment = IncidentTreatment.None, string treatmentNote = "");
void GiveStatement(IncidentPerson p, string statement);
void StartIncidentReview(IncidentReport report, string notes = "");   void ClassifyIncident(IncidentReport report, IncidentSeverity severity);
void RecordIncidentFindings(IncidentReport report, string rootCause = "", string outcome = "", string notes = "");
void MarkIncidentReportable(IncidentReport report, bool reportable, string authority = "", DateTime? dueAt = null);
void RecordAuthorityReport(IncidentReport report, string reference, DateTime? at = null);
void CloseIncident(IncidentReport report, string outcome = "");   void ReopenIncident(IncidentReport report, string why);
CorrectiveAction AssignCorrectiveAction(IncidentReport report, string what, Principal owner, DateOnly dueOn);
void CompleteCorrectiveAction(CorrectiveAction action, string note);
List<IncidentNotice> InformContacts(IncidentPerson about, string message = "");   void AcknowledgeIncidentNotice(IncidentNotice n, string response = "");
List<IncidentRegisterRow> IncidentRegister(DateOnly from, DateOnly to);   string IncidentRegisterCsv(DateOnly from, DateOnly to);
```

## Description    {#description}

### What does a report hold?   {#report}
A running number (`INC-00001`), who filed it (stamped from the caller, never chosen), when it happened and was reported,
a category and — when known — a severity, where, what happened and what was done there and then. Categories and
severities are the app's rows (`IncidentCategory`, `IncidentSeverity` with a rank). A category that `AsksAboutInjury`
asks who was hurt on the form. The person who filed it corrects the facts while it is `Open`; once a reviewer takes it
up it is the record. Nothing is deleted.

### Who was involved?   {#people}
`IncidentPerson` rows: hurt, involved or a witness, with an account (staff, a member, or a child or visitor with an
account they never sign in to — [managed accounts](https://osysharp.com/reference/security/accounts-kit/)) or just a name. Each carries the injury, the
care given, days away and their statement. A witness reads their own line, never the report, and writes their own
statement (`GiveStatement`). Photos and files go on the report (`KeepIncidentFile`, `AttachIncidentFile`).

### How is it reviewed?   {#review}
`StartIncidentReview` takes it up; `ClassifyIncident` sets its severity; `RecordIncidentFindings` keeps the cause
(reviewers only) and the outcome (which its reporter reads once it closes, unless the app says otherwise).
`AssignCorrectiveAction` sets what will stop it happening again, with an owner and a due date — the owner reads their
action and the report's number and category it carries, never the report, and marks it done. Each action's clock raises
`CorrectiveActionOverdue` once when it runs late. `CloseIncident` refuses while an action is open or the report waits
for its authority, naming what is left; `ReopenIncident` takes it back, the reason kept. Status, notes and review
fields move only inside these functions ([deny … except via](https://osysharp.com/reference/security/except-via/)).

### Who is told?   {#notices}
The app answers `IIncidentContacts` — next of kin, a carer — found, never wired ([App.Implementations<T>()](https://osysharp.com/reference/class/app-implementations/)); with
Osysharp.Guardianship, `Osysharp.IncidentReports.Guardianship` answers with a child's guardians by itself.
`ContactsToInform` lists who has not been told; `InformAboutIncident` / `InformContacts` send an `IncidentNotice` that
keeps exactly what they were told (the facts of that person's part and the reviewer's own words), raising
`IncidentNoticeSent` for the app to mail. They read their notice — never the report — and acknowledge it.

### When must it go to an authority?   {#authority}
A severity may carry `ReportWithinHours` and an `Authority` ("HSE (RIDDOR)", 240): classifying a report at it makes it
reportable, due that long after it was reported. A reviewer can set or clear one by hand (`MarkIncidentReportable`).
Each report's clock raises `IncidentAuthorityReportDue` `AuthorityWarningHours` before the deadline and
`IncidentAuthorityReportOverdue` when it passes, once each; `RecordAuthorityReport` keeps the authority's reference and
silences both.

### The register   {#register}
`IncidentRegister(from, to)` is every report of the period, one line each — number, when, category, severity, where,
who was hurt and how they were cared for, days away, status, the authority line, open actions — and
`IncidentRegisterCsv` the same as CSV, for an inspector, an insurer or a board.

### Which pages does it serve?   {#pages}
`/incidents` — report one; your reports, the actions you own, statements asked of you, what you were told.
`/staff/incidents` — the desk: what waits for review, what is under review, deadlines, late actions; one report open in
a dialog with the whole review. `/staff/incidents/register` and `/staff/incidents/setup`. Each stands in the app's
working shell with theme tokens only; take one over by declaring a component of the same name, or place
`MyIncidents`, `ReportIncidentForm`, `IncidentsDesk`, `IncidentDetail`, `IncidentRegisterView` or `IncidentSetup` on a
page of your own.

### Whose data is kept?   {#privacy}
What happened and a statement are `Personal.Content`, names `Personal.Identity`, an injury and the care given
`Personal.Special`. With Osysharp.Privacy, `Osysharp.Privacy.IncidentReports` arrives by itself ([Bridges — a package that arrives when an app uses the two it completes](https://osysharp.com/reference/project/bridges/)):
special-category data kept on a legal obligation, counted, copied and — when its period ends — erased from the lines
naming the person, while the report stays.

## Examples       {#examples}

### A workshop that tells a trainee's guardian and chases late actions   {#example-workshop}
```osy title="a training workshop: staff report, the safety lead reviews, a trainee's guardian is told" test app=ui-incident-reports-kit
app Workshop {
  use Osysharp.Identity@0;
  use Osysharp.Csv@0;
  use Osysharp.IncidentReports@0;
  use Osysharp.Storage;
  use Osysharp.Ui;
  use Osysharp.Workflow;
  model "model/**/*.osy";
}

using Osysharp.Identity;
using Osysharp.IncidentReports;

[Role] enum ShopRole { Authenticator, Trainee, Instructor, SafetyLead }
policy IsStaff => RoleGrant.Any(g => g.Member == user && (g.Role == ShopRole.Instructor || g.Role == ShopRole.SafetyLead));
policy ReportsIncidents => IsStaff;
policy ReviewsIncidents => RoleGrant.Any(g => g.Member == user && g.Role == ShopRole.SafetyLead);

app.Incidents = new IncidentsSetup { AuthorityWarningHours = 48, Organisation = "Northgate Training Workshop" };

/// Who signed a trainee up — the one told when the trainee is named in an incident.
entity Sponsor {
  [Required("Which trainee?")] Principal Trainee;
  [Required("Who sponsors them?")] Principal Contact;
  security { allow read when IsStaff; }
}

public class Sponsors : IIncidentContacts {
  public List<Principal> ContactsFor(Principal person) => Sponsor.Where(s => s.Trainee == person).Select(s => s.Contact).Take(5).ToList();
}

/// A reminder the safety lead sees when an action runs late.
entity LateAction {
  [MaxLength(1000)] string What = "";
  security { allow read when ReviewsIncidents; }
}

[On]
void NoteLate(CorrectiveActionOverdue e) { new LateAction { What = e.Action.What }; }
```

## See also       {#see-also}
- [The Guardianship kit — who acts for whom: children, carers, consents and emergency contacts](https://osysharp.com/reference/security/guardianship-kit/) — a child's guardians, told by the bridge
- [The UserAccounts kit — sign-in done properly, once](https://osysharp.com/reference/security/accounts-kit/) — an account for somebody named who never signs in
- [[Attachment] — a file readable wherever its row is](https://osysharp.com/reference/storage/attachment/) — photos, readable wherever the report is
- [deny … except via](https://osysharp.com/reference/security/except-via/) — the review moving only through the kit's functions
- [The Privacy kit — erasure that keeps only what the company must or may](https://osysharp.com/reference/security/privacy-kit/) — a person's incident record in their privacy requests
- **`kits/incident-reports/tests/`** — every behaviour above as a test, the screens under `--pixels`
