HOCO B2B
SRSRequirements

Audit trail & history

The append-only activity journal of sensitive actions, the business histories kept on orders, stock, prices and resellers, and the back-office viewer.

This area makes every critical action traceable "with user, date, time and context" (cahier §2.1, §3.1, §4.3, §4.4, §8, §10). It has two layers. The activity journal (AuditLog) records who did what, from which app and address — written by the server's audit module for every module. The business histories (order status changes and modifications, stock movements, price changes, reseller status and assignment changes, credit-limit and tour status changes) are structured tables written by each domain module and shown where the record is viewed. The journal is read in the back-office (BO-63); histories appear in the back-office, and the parts that concern them in the reseller apps (RA, RW).

IDRequirementReleasePrioritySourceApps
AUD-01Activity journal: logins, creations, modifications, validations, exports, deletions with user, time and contextV1MUST§3.1, §10API · BO
AUD-02Entity histories: order changes, status changes, stock movements and price changes are kept and viewable in contextV1MUST§4.3, §4.4, §8API · BO
AUD-03Audit log viewer with filters and export for authorised usersV1SHOULD§10BO

Requirements

AUD-01 — Activity journal

ReleasePrioritySourceAppsOwner tasks
V1MUSTcahier §3.1, §10API · BOSRV-07 · DSH-12

Statement — The system shall record in an append-only activity journal every sign-in, creation, modification, status change, validation, refusal, export, import, permission change, override and deletion, with the actor, the time and the context of the action.

Rules

  1. Journaled: every successful mutating operation on a business record (CREATE, UPDATE, DELETE, STATUS_CHANGE, VALIDATE, REJECT); sign-ins (LOGIN, LOGIN_FAILED, LOGOUT); exports (EXPORT with the list or report, the filters and the row count); imports (IMPORT with the file, counts and mode); role and permission changes (PERMISSION_CHANGE); overrides of a business control (OVERRIDE with the control and the reason); actions of the system itself (actor SYSTEM: automatic statuses, expiries, scheduled jobs).
  2. Reads are not journaled, with two exceptions: issuing a download URL for a private store document (ID card, RC, NIF…) and every export.
  3. Each entry stores: occurredAt (server time, plus the device time for offline actions), the actor (user id, user type and roles at that moment, or SYSTEM), the action (AuditAction), the entity type, id and business number (CMD-2026-000158), the changed fields with before and after values (only the fields that changed), the reason when the operation requires one, and the context: client (ClientApp), app version, IP, user agent or device id, session id, request id and operation id (admin.orders.validate).
  4. Never written: passwords, one-time codes, tokens, file contents. Financial values are written — the journal itself is restricted to audit.view.
  5. The entry is inserted in the same database transaction as the change: no change without an entry, no entry for a change that was rolled back. Sign-in failures are written outside business transactions.
  6. Append-only: no operation updates or deletes entries, and the application's database role has only INSERT and SELECT on the journal table.
  7. Offline actions replayed through sync.batch are journaled once, with the device time and the reception time and ClientApp = DELEGATE_APP; an idempotent replay (REPLAYED) adds nothing.
  8. Not journaled because they are data, not actions: location pings, notification deliveries, cart edits (the order created at checkout is journaled).
  9. Retention follows the policy validated with HOCO under Law 18-07 (SEC-08); the proposed default is 24 months online, then archived.
ValueUI label (fr)Meaning
LOGINConnexion
LOGIN_FAILEDÉchec de connexion
LOGOUTDéconnexion
CREATECréation
UPDATEModification
DELETESuppression
STATUS_CHANGEChangement de statut
VALIDATEValidation
REJECTRefus
EXPORTExport
IMPORTImport
PERMISSION_CHANGEChangement de droits
OVERRIDEDérogation

Acceptance criteria

  • Validating order CMD-2026-000158 creates one VALIDATE entry with the actor, their roles, app DASHBOARD, IP, request id and the order number.
  • Changing a reseller's main phone creates an UPDATE entry whose changes contain the old and new phone.
  • A validation refused with 422 STOCK_INSUFFICIENT creates no entry; the same validation with a stock override creates VALIDATE and OVERRIDE entries with the reason.
  • A visit note recorded offline and replayed creates one entry carrying both times; replaying the same Idempotency-Key adds no entry.
  • UPDATE audit_logs … run with the application's database role fails with a permission error.
  • The entries of a password reset contain neither the password nor the code.
  • Opening a reseller's ID card from the back-office creates an entry naming the document.

Data — AuditLog (partitioned by month), Session (context).

Interfaces

Notes / open points — The retention duration is one of the data-retention decisions listed in cahier §15 (see the decision register).

AUD-02 — Business histories kept and shown in context

ReleasePrioritySourceAppsOwner tasks
V1MUSTcahier §4.3, §4.4, §8API · BOSRV-02

Statement — The system shall keep a structured, never-edited history of order statuses and modifications, stock movements, price changes and the other lifecycle changes listed below, and shall show each history where the record is viewed.

Rules

  1. Histories, when they are written and where they are shown:

    HistoryModelWritten onShown in
    Order statusOrderStatusChange (from, to, time, actor, reason, client)every transition, including automatic onesRA-22, RW-09, BO-39
    Order modificationsOrderChange (line or field, before, after, reason, actor)admin.orders.modify, address or payment-method changeBO-39; a summary to the reseller
    StockStockMovement (type, quantities, balance after, reference, actor)every change of physical or reserved stockBO-34, product editor
    PricesPriceChange (variant, field — priceSuperGros, priceDemiGros, priceDetail, purchasePrice, recommendedPrice, vatRate — old, new, source, actor)product editor, importsBO-28 (price history)
    Reseller statusResellerStatusChangeevery lifecycle change, manual or automaticBO-11
    Reseller assignmentResellerAssignment (delegate, zone, from, to, reason)every assignmentBO-11
    Customer typetype history of the reseller (from, to, time, actor, reason)declaration, confirmation at validation, back-office changeBO-11
    Returnsstatus history of ReturnRequest, reception quantities, credit noteevery return transitionBO-69, RA-40
    Reseller profile fieldsAuditLog UPDATE entries of the resellerprofile.update, admin.resellers.update, account claimBO-11 Historique tab
    Credit limitCreditLimitChange (old, new, blocked, reason)admin.credit.updateBO-46
    Tour statusTourStatusChangeevery tour transitionBO-23
  2. Rows are written in the same transaction as the change and never updated or deleted; a correction is a new row.

  3. Each row stores the actor (user id, or SYSTEM) and the time. The back-office shows « Système » for automatic changes; the reseller apps show « HOCO » instead of staff names.

  4. Times are displayed in Africa/Algiers: « 14 mai 2026 à 10:32 ».

  5. Histories are business records kept for the life of the record, independently of the journal's retention; archiving a product or disabling a user keeps them.

Acceptance criteria

  • After an order goes SUBMITTED → VALIDATED → PREPARING, admin.orders.history returns three status rows in order with actors, and the reseller's orders.get timeline shows the same three steps with « HOCO » as actor.
  • Changing a line quantity from 10 to 6 with the reason « Rupture partielle » adds an OrderChange row with both quantities and the reason.
  • Changing a variant's Demi-gros price from 2 390,00 DA to 2 490,00 DA HT adds a PriceChange row (field priceDemiGros) visible in BO-28's price history.
  • Every reservation, release and shipment of a variant appears in BO-34 with the order number as reference.
  • Archiving a product keeps its price history readable.

Data — OrderStatusChange, OrderChange, StockMovement, PriceChange, ResellerStatusChange, ResellerAssignment, CreditLimitChange, TourStatusChange, AuditLog.

Interfaces

AUD-03 — Audit log viewer with filters and export

ReleasePrioritySourceAppsOwner tasks
V1SHOULDcahier §10BODSH-12

Statement — The system shall give authorised users a searchable, filterable and exportable view of the activity journal.

Rules

  1. The viewer (BO-63) calls admin.audit.list, which requires audit.view (granted to SUPER_ADMIN by default).
  2. Filters: actor (user picker, including Système), user type, action (several), entity type, entity id or business number, client app, IP, and a date range — default the last 7 days, at most 92 days per query (400 VALIDATION_FAILED beyond). Results are sorted newest first, paginated with page/pageSize (at most 200).
  3. Each row shows time, actor, action, a link to the record, a one-line summary (« Statut VALIDATED → PREPARING »), app and IP; expanding it shows the before/after changes, the reason, the request id and the user agent.
  4. Export to CSV or XLSX of the current filter goes through the export centre (ANA-05), requires audit.export, is limited to 100 000 rows and is itself journaled as EXPORT.
  5. Records that have a business number (orders, resellers, invoices, tours) offer a « Journal » link that opens the viewer filtered on that record, for users holding audit.view.
  6. The first page answers in under 2 seconds on a journal of 10 million entries for a 7-day window.

Acceptance criteria

  • A super administrator filters on CMD-2026-000158 and sees every action on that order, newest first.
  • Filtering on action OVERRIDE over 30 days lists every forced validation with its reason.
  • A 120-day range returns 400 VALIDATION_FAILED.
  • A commercial administrator without audit.view does not see the menu entry and gets 403 PERMISSION_DENIED from admin.audit.list.
  • An XLSX export of the filtered view arrives in the export centre and adds an EXPORT entry to the journal.

Data — AuditLog, ExportJob.

Interfaces

On this page