This is an internal working record, not an everyday instruction. It was written while the system was being rebuilt, for whoever maintains it. If you are here to do today's work, use the everyday documents instead: Procedures · Processes · Runbooks · The working day, step by step
CTC Billing, QBO, Files And Email Policy Decision Matrix¶
- Status:
CURRENT P6-007 POLICY DECISION INPUT - Operating profile:
ctc-execution - Source reconciliation:
CTC_BILLING_QBO_FILES_EMAIL_RECONCILIATION.md - Composite process:
PROC-BMS-BILLING-CLOSE-CTC - Atomic owners:
PROC-BMS-TRANSACTION-LIFECYCLE-CTCPROC-BMS-AR-BILLING-CONFIRM-CTCPROC-BMS-AR-QBO-DELIVERY-CTCPROC-BMS-TRANSACTION-DOCUMENT-CTCPROC-TMS-BOL-EMAIL-CTCPROC-TMS-PACKING-LIST-EMAIL-CTC- Scope: document current facts, recommended target policies, unresolved decisions and owners before Runtime implementation or migration.
- Does not authorize: code, schema, provider, Wiki DB, role/config, deployment or Production changes.
1. Decision Vocabulary¶
| Value | Meaning |
|---|---|
FIXED CURRENT FACT |
Verified current source behavior that must be preserved or intentionally migrated. |
USER-APPROVED |
User decision already fixed and not open to reinterpretation. |
RECOMMENDED |
Proposed policy based on current integrity and migration requirements; requires owner/user approval before implementation. |
OPEN |
Material policy or operational ownership is unresolved. |
CURRENT COMPATIBILITY |
Existing behavior may remain temporarily but is not the target contract. |
DEFERRED |
Intentionally postponed with owner and activation condition. |
REJECTED |
Explicitly prohibited direction. |
A recommendation is not current behavior. An open item must not be filled by implementation convenience.
2. Decision Summary¶
| ID | Topic | Current fact | Recommended/fixed direction | Status | Primary owner | Blocks |
|---|---|---|---|---|---|---|
BILL-POL-010 |
Generic close allowed fields | Current close accepts normalized UI-supplied T_TRANSACTION columns for selected IDs. |
Replace target behavior with an explicit CloseTransactions command and allowlisted fields/status predicates. |
RECOMMENDED |
BMS transaction + P5/P6 | Target write packet, correction policy |
BILL-POL-020 |
Mixed-company/value batch | Current UI can apply first-row/common values to all selected rows; server does not prove compatibility. | Server must group or reject rows whose billing company, account or close values are incompatible. | RECOMMENDED |
BMS transaction | Safe bulk close |
BILL-POL-030 |
Prior-state predicate | Current generic close lacks a documented prior-state predicate. | Every target close/correction transition uses explicit allowed source states and exactly-one/per-row affected result. | RECOMMENDED |
BMS transaction | State machine, idempotency |
BILL-POL-040 |
Synced transaction edit/delete | Current generic paths do not provide one approved policy for rows already represented in QBO. | Block ordinary edit/delete after provider sync; use explicit accounting correction/void/reconciliation procedure. | RECOMMENDED |
Accounting owner + QBO owner | Data integrity, audit |
BILL-POL-050 |
Source transaction idempotency | Current source-specific create/delete behavior varies by adapter and relation. | Define tenant + source UUID + account + semantic transaction type as duplicate identity. | RECOMMENDED |
BMS transaction + source modules | Create replay, migration |
BILL-POL-060 |
AR Review requirement | Review-first is an operator safety practice; current top-level Complete can use defaults. | Require server-confirmed preview fingerprint or equivalent recomputation at confirm; UI Review may remain optional only when same authoritative calculation is used. | RECOMMENDED |
AR Billing | Stale preview, hidden defaults |
BILL-POL-070 |
Active container AR uniqueness | No proven active booking/container AR uniqueness or serialized confirm exists. | One active container AR per tenant + billing scope + booking UUID + container UUID, with explicit invoice version/correction semantics. | RECOMMENDED |
AR Billing + DB owner | Duplicate invoices, migration |
BILL-POL-080 |
Unsynced AR rewrite | Current unsynced AR header is rewritten and old lines soft-deleted. | Preserve current bounded rewrite only until explicit invoice-version/correction history is approved; target command records version lineage. | CURRENT COMPATIBILITY |
AR Billing | Audit, PostgreSQL model |
BILL-POL-090 |
Post-confirm correction | Current approved correction path after local confirm but before QBO is unclear. | Define CorrectLocalContainerInvoice with state predicate READY/ERROR and immutable audit/version evidence; prohibit raw row edits. |
OPEN |
Accounting owner | Operator recovery, M4 |
BILL-POL-100 |
Automatic QBO handoff | Browser calls QBO after local confirm; interruption can leave READY with no attempt. |
Local confirm records a durable QBO effect intent when delivery is applicable; worker or explicit send command owns attempts. | RECOMMENDED |
P6-004/P12 + QBO owner | Durable delivery |
BILL-POL-110 |
QBO group identity | Current grouping is per transaction or customer-key + invoice number. | Persist immutable effect group identity from sorted transaction UUIDs + customer ref + invoice number + payload hash. | RECOMMENDED |
QBO application | Idempotency/reconciliation |
BILL-POL-120 |
QBO provider idempotency | Current client has no provider idempotency key or search. | Add provider-supported request identity where available and always implement provider search/reconcile before resend. | RECOMMENDED |
QBO integration | Duplicate provider invoice |
BILL-POL-130 |
SYNCING timeout |
Current stale SYNCING recovery is not implemented. |
Do not time-reset blindly. After threshold, reconcile provider using effect identity and evidence, then mark SYNCED, FAILED_RETRYABLE, or MANUAL_REVIEW. |
OPEN |
Accounting/QBO support owner | Worker, Runbook |
BILL-POL-140 |
QBO_ERROR dual use |
Current field stores claim token during SYNCING, then error text. |
Separate effect intent/attempt identity from safe error detail in target model; retain field only as compatibility projection. | RECOMMENDED |
P5/P12/QBO owner | Target data model |
BILL-POL-150 |
QBO correction/void | Current client creates invoices only. | Provider correction, void/delete and local reconciliation require separate approved commands and accounting authority; ordinary resend is not correction. | OPEN |
Accounting owner | Synced correction SOP |
BILL-POL-160 |
Token refresh ownership | Token refresh occurs in invoice request path and writes tenant config. | Platform integration credential service owns refresh; business command consumes a valid provider session without owning secrets. | RECOMMENDED |
Platform/P4/P12 | Security, worker |
BILL-POL-170 |
File object/link model | Current T_FILE use combines object metadata and business link. |
Target model separates FileObject and FileLink; first MySQL adapter may map both to current rows only with explicit reference rules. |
RECOMMENDED |
Shared Files/P5/P12 | Safe migration/delete |
BILL-POL-180 |
Shared-object delete | A physical path can have multiple active links; storage delete behavior differs. | Unlink business relation first; delete object only when no active links/retention hold remain and cleanup is explicitly owned. | RECOMMENDED |
Shared Files | Data loss prevention |
BILL-POL-190 |
Upload/link atomicity | Object upload and MySQL registration are separate. | Record upload intent/result and make link creation idempotent; orphan cleanup is a separately reconciled worker action. | RECOMMENDED |
Shared Files/P6-004 | Partial recovery |
BILL-POL-200 |
File link uniqueness | Current retry can create duplicate links and sequence allocation can race. | Define active uniqueness by tenant + file-object identity + business target + link type; order is presentation metadata, not identity. | RECOMMENDED |
Shared Files/DB owner | Duplicate links |
BILL-POL-210 |
File retention | Current process lacks one approved retention/legal-hold policy. | Retention and legal hold are explicit metadata/policy; user unlink does not bypass retention or audit. | OPEN |
Operations/legal/platform | Object cleanup |
BILL-POL-220 |
Durable email effect ledger | BOL and Packing List return provider results but persist no durable send ledger. | Add email intent, attempt and reconciliation records before migrating sends to worker. | RECOMMENDED |
P6-004/P12 + Gmail owner | No-blind-retry, audit |
BILL-POL-230 |
BOL email identity | Current identity is transload/reference/recipient/subject/time. | Use immutable intent UUID + source UUID + recipient-set hash + attachment-set hash + content version. | RECOMMENDED |
TMS/Gmail owner | Duplicate reconciliation |
BILL-POL-240 |
Packing target-part identity | Current Results identify target/part only in response memory. | Persist batch UUID + target + part index/total + content/attachment hash; permit resume of only missing/failed parts. | RECOMMENDED |
Booking/Gmail owner | Partial send recovery |
BILL-POL-250 |
Gmail unknown result | Current timeout requires manual Sent search. | Worker/support must search by provider/message identity or deterministic headers before resend; unknown remains a first-class state. | RECOMMENDED |
Gmail integration | Duplicate sends |
BILL-POL-260 |
Recipient source ownership | Company email rows supply BOL/Packing recipients. | Recipient categories remain tenant-configured master data with named business owner and last-review evidence. | OPEN |
Operations/customer master owner | Wrong recipient risk |
BILL-POL-270 |
Username-based admin override | admin redirects email to a fixed developer address. |
Remove from target policy; replace with explicit environment-safe test-recipient configuration unavailable in ordinary Production operation. | RECOMMENDED |
Platform/Operations | Tenant safety |
BILL-POL-280 |
BOL send completion | No durable local send status. | Completion requires provider reconciliation; future local projection must reference a durable email effect record, not transload flags. | RECOMMENDED |
TMS/Gmail owner | Runbook/Wiki |
BILL-POL-290 |
Packing batch atomicity | Target/part sends are sequential and irreversible. | Treat every target-part as an independent effect under one batch; preserve successes and resume only unresolved parts. | RECOMMENDED |
Booking/Gmail owner | Partial result |
BILL-POL-300 |
Composite daily close | No stored composite status. | Keep as human/composite reconciliation. Do not create one universal BILLING_CLOSED field. |
FIXED CURRENT FACT |
Operations Billing | Process integrity |
BILL-POL-310 |
Daily close owner/cadence | Named accountable owner, cutoff and escalation are not approved. | Assign accountable role, normal cadence, unresolved-item cutoff and escalation evidence. | OPEN |
Operations owner | Field acceptance, Wiki |
BILL-POL-320 |
Role/API matrix | Current menu/module access is data-driven; row-level negative matrix incomplete. | P2/P4 must define semantic capabilities and test page/API/record allow/deny for Billing, Files and provider actions. | OPEN |
P2-007/P4 | M3/M4 |
BILL-POL-330 |
Provider effects in web request | Current QBO/Gmail effects run in request path. | Durable retryable provider effects move to Node worker after intent commit; synchronous preview/read remains Web/API. | RECOMMENDED |
P12/P6-004 | Reliability |
BILL-POL-340 |
PostgreSQL timing | DB transition is planned later. | Preserve accepted TypeScript/MySQL semantics first; do not combine first provider/transaction cutover with PostgreSQL. | USER-APPROVED |
P11/P12 | Migration order |
3. Generic Transaction Decisions¶
BILL-POL-010 — Close command shape¶
Current fact¶
The current close route accepts selected transaction IDs plus a normalized set of actual T_TRANSACTION columns. A blank invoice number is removed, and the remaining fields are bulk-applied.
Risk¶
- browser/schema shape becomes the command contract;
- unintended new columns can become writable through future UI/helper changes;
- no state-specific validation;
- mixed selections can receive one common value;
- response does not identify each row's final state.
Recommendation¶
Define:
CloseTransactions
with a bounded DTO such as:
transactionIds[]
completeDate
invoiceNumber?
checkNumber?
remark?
expectedVersion/updatedAt per row or batch snapshot
Server resolves billing company/account/source and rejects incompatible rows. Return per-row exact readback.
Status¶
RECOMMENDED; no Runtime change authorized here.
BILL-POL-030 — Prior-state and repeat behavior¶
Target transitions must declare:
allowed current states
terminal/locked provider states
expected row version
exact affected row count
repeat behavior
correction path
A repeat after unknown response rereads all selected IDs. It does not reapply close blindly.
BILL-POL-040 — Provider-synced local mutation¶
Ordinary generic edit/delete must not mutate a provider-synced financial record as if no external representation exists.
Target separation:
EditDraftTransaction
CloseTransaction
CorrectLocalTransaction
RequestProviderCorrection
ReconcileProviderCorrection
Deletion of a source relation, local transaction and provider invoice are separate effects with separate authority.
4. AR Billing Decisions¶
BILL-POL-060 — Preview consistency¶
The target does not need to force an extra modal click when it can guarantee the same result through server recomputation. It must guarantee:
- source/rate/preset version is current at confirm;
- client-supplied calculated amount is not authoritative;
- lines returned by preview can be compared with committed lines;
- material drift is shown before an irreversible next effect.
Possible target approaches:
A. previewToken + source fingerprint required at confirm
B. confirm recomputes and returns a conflict when preview fingerprint changed
C. single command recomputes and requires explicit acknowledgement of returned final lines
Owner decision remains required.
BILL-POL-070 — Active invoice uniqueness¶
Recommended identity:
tenant
+ BILLING_SCOPE='CONTAINER'
+ booking UUID
+ container/equipment UUID
+ active/non-void invoice generation
A later corrected version should relate to the prior invoice rather than silently replacing its historical meaning.
Current unsynced rewrite can remain only as bounded compatibility until the version/correction model is accepted.
5. QBO Decisions¶
BILL-POL-100 — Durable delivery intent¶
Recommended sequence:
local AR confirm transaction
-> persist QBO delivery intent when applicable
-> commit local invoice and intent
-> worker claims intent
-> provider create/search
-> persist attempt/result
-> reconcile local invoice projection
The business request may expose PENDING_QBO after local commit. It must not wait for provider completion to report local confirm success.
BILL-POL-130 — Stale SYNCING¶
A time threshold alone does not prove failure. Required reconciliation inputs:
- effect intent/attempt ID;
- sorted local transaction UUIDs;
- customer reference;
- document number;
- total amount/currency;
- payload hash;
- provider request/response metadata;
- local claim time/actor;
- provider search result.
Allowed target dispositions:
SYNCED
FAILED_RETRYABLE
FAILED_FINAL
UNKNOWN_PROVIDER_RESULT
MANUAL_REVIEW
Releasing back to READY requires provider absence or an accepted duplicate-risk decision.
BILL-POL-150 — Provider correction¶
This family currently documents invoice creation. Provider correction/void/delete is a separate accounting capability and must specify:
- normal actor and approval;
- provider operation allowed;
- local status and correction relation;
- customer/document-number behavior;
- file/email downstream impact;
- audit and evidence;
- reversal versus replacement;
- tax/accounting retention.
Do not implement correction by clearing QBO_INVOICE_ID and resending.
6. File Decisions¶
BILL-POL-170 — Conceptual model¶
Target concepts:
FileObject
- storage provider/key
- size/hash/content type
- original filename
- created/retention/cleanup state
FileLink
- target entity type/UUID
- file object UUID
- link type/sequence/label
- active lifecycle
FileReadability
- current object availability/check result
FileCleanupDisposition
- eligible/held/referenced/deleted/failed/manual review
The first MySQL adapter may retain T_FILE, but application contracts must not expose path-sharing as business identity.
BILL-POL-180 — Delete semantics¶
Required target command split:
UnlinkFileFromTransaction
EvaluateFileObjectCleanup
DeleteUnreferencedFileObject
ReconcileFileObject
DELETE /files/{id} compatibility must not become the target domain command without reference and retention checks.
7. Email Decisions¶
BILL-POL-220 — Effect ledger¶
Recommended target entities:
EmailIntent
EmailTarget
EmailPart
EmailAttempt
EmailReconciliation
At minimum preserve:
- source capability/entity UUID;
- intended recipient set;
- subject/body/content version;
- attachment object UUIDs/hashes;
- target (
BOL,CUSTOMER,INSPECTOR); - part index/total;
- attempt number;
- provider message/thread IDs;
- result/error/unknown state;
- actor/request/correlation ID.
BILL-POL-240 — Packing part resume¶
Target retry rules:
- do not rebuild already accepted parts unless content changed and a new version is intentionally sent;
- retry only unresolved target/part identities;
- if generated attachment partitioning changes, create a new batch version rather than mixing old/new parts;
- show the operator every target/part state;
- preserve provider message IDs for each success.
BILL-POL-270 — Test recipient override¶
Target test-safety contract:
explicit non-Production or approved test mode
+ tenant/environment configuration
+ visible banner/result recipient
+ audit/correlation
+ impossible to activate silently in ordinary Production
Username comparison is rejected as the target selector.
8. Composite Close Decisions¶
BILL-POL-300 — No universal status¶
The daily composite remains a reconciliation view. It may have a derived worklist/disposition record later, but it must not mutate or replace child states.
Possible derived dispositions:
VERIFIED
CARRIED
NOT_APPLICABLE
BLOCKED
UNKNOWN
If persisted, each disposition references exact child identity/evidence and owner. It is not a business completion authority.
BILL-POL-310 — Operating ownership¶
Required user/operations decision:
| Question | Decision needed |
|---|---|
| Accountable role | Who owns daily Billing/document close? |
| Cadence | Continuous, end-of-shift, end-of-day, or accounting cutoff? |
| Cutoff timezone | Tenant operating timezone and business day definition. |
| Carry threshold | When does unresolved QBO/email/file work escalate? |
| Escalation owner | Accounting, operations manager, system support, provider support. |
| Required evidence | IDs, screenshots, provider message/invoice IDs, amounts and timestamps. |
| Retention | Where is the reconciliation record retained? |
Until approved, Wiki content must describe child procedures and recovery without inventing an SLA.
9. Role And Capability Recommendations¶
Proposed semantic capabilities for later P2/P4/P12 mapping:
bms.transaction.view
bms.transaction.create
bms.transaction.edit
bms.transaction.close
bms.transaction.correct
bms.transaction.delete
bms.ar-billing.view
bms.ar-billing.preview
bms.ar-billing.confirm
bms.ar-billing.correct
bms.qbo.view
bms.qbo.request-delivery
bms.qbo.reconcile
bms.qbo.correct
files.transaction.view
files.transaction.upload
files.transaction.link
files.transaction.unlink
files.object.cleanup
tms.bol-email.view
tms.bol-email.send
tms.bol-email.reconcile
tms.packing-email.view
tms.packing-email.send
tms.packing-email.reconcile
operations.billing-close.review
These names are target semantics, not proof of current role IDs or menu rows.
10. Decision Activation Order¶
Before any new current-Runtime Billing write¶
Resolve or explicitly bound:
BILL-POL-010
BILL-POL-020
BILL-POL-030
BILL-POL-040
BILL-POL-320
Before AR/QBO migration or worker implementation¶
Resolve:
BILL-POL-060 through BILL-POL-160
BILL-POL-320
BILL-POL-330
Before File migration¶
Resolve:
BILL-POL-170 through BILL-POL-210
BILL-POL-320
Before Gmail worker migration¶
Resolve:
BILL-POL-220 through BILL-POL-290
BILL-POL-320
BILL-POL-330
Before Wiki field acceptance¶
Resolve:
BILL-POL-260
BILL-POL-310
BILL-POL-320
11. Explicitly Rejected Shortcuts¶
- One
BILLING_COMPLETEorDOCUMENT_SENTcolumn for all children. - Treating
QBO_SYNC_STATUS='ERROR'as provider absence. - Resetting stale
SYNCINGsolely by age and resending. - Clearing provider IDs to force a resend.
- Reusing
QBO_ERRORas permanent intent identity in the target model. - Treating object path as the only file identity.
- Deleting a physical object when one selected link is deleted without checking other links/retention.
- Retrying the entire Packing List target/batch after one part failure without reconciliation.
- Using username, numeric tenant ID or customer name as target policy.
- Putting provider calls, object cleanup or multipart replay directly in React components or page-owned Server Actions.
- Migrating Billing/QBO/Gmail and PostgreSQL in one cutover.
12. Review Ledger¶
| Decision ID | Reviewer | Decision | Date | Evidence/notes |
|---|---|---|---|---|
No OPEN or RECOMMENDED row becomes approved merely because implementation code was written.
---¶
Source:
docs/processes/CTC_BILLING_QBO_FILES_EMAIL_POLICY_DECISION_MATRIX.md— ctc repository · This page is an English translation of the source document. Identifiers, file paths and code symbols are unchanged.