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 Parity And Cutover Matrix¶
- Status:
CURRENT P6/P12 MIGRATION INPUT - Operating profile:
ctc-execution - Source reconciliation:
CTC_BILLING_QBO_FILES_EMAIL_RECONCILIATION.md - Policy decisions:
CTC_BILLING_QBO_FILES_EMAIL_POLICY_DECISION_MATRIX.md - Rebuild packet:
CTC_BILLING_QBO_FILES_EMAIL_CAPABILITY_REBUILD_PACKET.md - Target stack: React + Next.js + framework-independent TypeScript + MySQL repositories + durable Node worker; PostgreSQL later.
- Does not activate: any migration wave, dual writer, DB schema, provider effect, deployment or Production change.
1. Migration Principle¶
Migration follows business capability and checkpoint authority, not current page or file layout.
current source characterization
-> target read model
-> read-shadow parity
-> one bounded write command
-> one authoritative writer
-> exact readback and effect reconciliation
-> rollback rehearsal
-> target-role stabilization
-> caller-zero
-> legacy retirement
The following cannot be cut over as one unit:
generic transaction
AR local confirm
QBO provider delivery
file object/link
BOL email
Packing List target-part email
daily composite reconciliation
They share an operational close but own independent state and recovery.
2. Global Gates¶
Every write/effect wave requires all applicable gates.
| Gate | Required evidence |
|---|---|
G-010 Source baseline |
Exact current source revision, schema identity, deployment identity and active caller inventory. |
G-020 Process contract |
Accepted business outcome, completion, non-implication, normal/negative/recovery behavior. |
G-030 Role/capability |
Target tenant × role × page/API/record/action allow/deny matrix. |
G-040 Data contract |
Authoritative identity, state, fields, units, relationships, audit/correction and retention. |
G-050 Interface contract |
Semantic command/query DTO, stable errors, exact readback and idempotency. |
G-060 Effect contract |
Intent, attempt, provider/object result, unknown state, retry/reconcile/manual recovery. |
G-070 One writer |
One explicit selector/cohort chooses one writer; no PHP/TypeScript dual mutation. |
G-080 Rollback |
Tested selector reversal from current MySQL state without replaying committed business/provider effects. |
G-090 Parity |
Stable scenario IDs pass for old/new reads or accepted intentional difference. |
G-100 Observation |
Request/process/effect IDs, logs/metrics, support runbook and bounded observation period. |
G-110 Knowledge |
Process, Runbook, Wiki stable topics and current/future route links synchronized. |
G-120 Caller-zero |
Static and runtime callers classified; unknown caller count is zero before deletion. |
A UI that looks correct is not sufficient for a write/effect wave.
3. Wave Overview¶
| Wave | Capability | Initial target | Writer/effect owner after cutover | Main rollback |
|---|---|---|---|---|
BILL-W0 |
Shared context and observability | TypeScript tenant/actor/error/request/effect IDs | No business writer change | Remove target read path |
BILL-W1 |
Billing composite and workbench reads | React + Next.js read-only projections from MySQL | Current PHP writers remain | Route users to current pages |
BILL-W2 |
Generic transaction semantic reads | TypeScript repositories/queries | Current PHP writers remain | Disable target queries |
BILL-W3 |
Generic transaction create/edit/close/correct | TypeScript application commands, MySQL | Selected capability writer only | Disable target commands; resume PHP from current rows |
BILL-W4 |
AR candidate/preview/confirm | React review + TypeScript confirm, MySQL | TypeScript AR confirm writer | Resume PHP confirm only after exact state reconciliation |
BILL-W5 |
QBO intent and read model | Durable intent/attempt/reconciliation + worker shadow | PHP direct send remains until W6 | Disable shadow worker/read model |
BILL-W6 |
QBO delivery | Node worker + TypeScript reconciliation | Worker is only provider-send owner | Stop new attempts; reconcile in-flight; restore PHP send only for unresolved intents after decision |
BILL-W7 |
File object/link reads and upload | Typed object/link repository with current storage | One object/upload/link owner per command | Restore current upload/link UI; keep objects/links |
BILL-W8 |
File unlink/cleanup | Reference-aware unlink + deferred cleanup worker | TypeScript/File worker | Stop cleanup; retain objects; restore current unlink only after reference check |
BILL-W9 |
BOL email intent/send | Durable email intent + worker | Worker only | Stop new attempts; current send restored only after in-flight reconciliation |
BILL-W10 |
Packing List target-part send | Durable batch/target/part intents + worker | Worker per target-part | Stop unresolved attempts; preserve successes; restore current endpoint only for new batch versions |
BILL-W11 |
Daily close reconciliation | React derived worklist/disposition | Composite remains non-mutating | Return to manual current cross-page review |
BILL-W12 |
PHP/legacy retirement | Caller-zero and route removal | Target platform | Re-enable compatibility routes only while data/contract remains supported |
BILL-W13 |
PostgreSQL later | Repository/data cutover | TypeScript application unchanged | DB failback per P11; never combined with first business/effect cutover |
4. Wave BILL-W0 — Shared Context And Observability¶
Scope¶
- strict tenant and effective actor/subject context;
- semantic request ID and process/effect correlation;
- stable public error envelope;
- source revision/schema/config/deployment identity in support evidence;
- no business write or provider effect.
Required parity¶
| Concern | Current | Target parity |
|---|---|---|
| Tenant | Legacy context/session with compatibility fallback | Same selected tenant, explicit target context; no caller-supplied authority. |
| Actor | Session user and current role/menu | Same effective actor plus impersonation subject when applicable. |
| Timezone | Current configured/runtime behavior | Same business-date interpretation, explicitly sourced. |
| Error | Current envelopes vary | Stable semantic code while preserving safe user meaning. |
| Request trace | Current request/debug/log IDs | One request ID propagated to application and effect intent. |
Exit¶
Target queries can execute read-only against the same MySQL data with traceable tenant/actor/request identity.
5. Wave BILL-W1 — Read-Only Composite And Workbench¶
Target views¶
- Billing daily checkpoint worklist;
- generic transaction list/detail;
- AR candidate/workbench/detail;
- QBO local/provider reconciliation projection;
- transaction file list/readability projection;
- BOL/Packing email readiness/result projection where current evidence exists.
Parity dimensions¶
| ID | Old source | New projection | Required comparison |
|---|---|---|---|
BILL-PAR-010 |
Generic transaction list/detail | GetTransactions, GetTransactionDetail |
IDs/UUIDs, source/account/company, amounts, status, close fields, lines. |
BILL-PAR-020 |
AR Billing workbench | GetArBillingWorkbench |
Candidate count, booking/container, customer, warnings, totals, invoice/QBO state. |
BILL-PAR-030 |
AR preview | PreviewContainerInvoice read-only |
Charge source/type/qty/rate/amount/description and total. |
BILL-PAR-040 |
Current QBO columns | GetQboReconciliation |
transaction group, local state/ID/doc/error, provider evidence when available. |
BILL-PAR-050 |
Current file list/download | GetTransactionFiles |
file identity, type/name/order, target relation, URL/readability. |
BILL-PAR-060 |
Current BOL readiness | GetBolEmailReadiness |
source/reference/recipient/scale/files/blocked reason. |
BILL-PAR-070 |
Current Packing model/readiness | GetPackingEmailReadiness |
booking/equipment/options/targets/recipient/part plan. |
BILL-PAR-080 |
Manual daily cross-page review | GetBillingCloseWorklist |
applicable checkpoints and current unresolved owner, no invented completion. |
Rollback¶
Remove/rewrite target navigation and use existing pages. No data/effect rollback.
6. Wave BILL-W2 — Generic Transaction Semantic Reads¶
Purpose¶
Establish a typed repository/query boundary before changing current writes.
Required contracts¶
GetTransactionSources
GetTransactions
GetTransactionDetail
GetTransactionCloseEligibility
GetTransactionCorrectionHistory
Required current-source reconciliation¶
- source type and relation identity;
- UUID coverage versus numeric-only compatibility;
- active line calculation;
- status/close field meanings;
- billing company/account derivation;
- provider/file relations;
- current delete/soft-delete semantics.
Exit¶
All later commands can reread exact authoritative state without importing current giant helpers or generic table mutation.
7. Wave BILL-W3 — Generic Transaction Writes¶
Candidate command order¶
CreateSourceTransactions
EditDraftTransaction
CloseTransactions
CorrectLocalTransaction
DeleteOrVoidDraftTransaction
Do not start with delete/correction if policy remains open.
One-writer selector¶
Recommended selection key:
capability/source type + tenant/cohort
Example:
TRUCKING AR create/close for one approved tenant
The same source/account capability cannot write through both PHP and TypeScript.
State parity¶
| Command | Old behavior to characterize | Target required behavior |
|---|---|---|
| Create | Source-specific helper may detect existing related IDs | Explicit idempotency and per-source result. |
| Edit | Generic schema-shaped mutation | Allowlisted semantic fields and state predicate. |
| Close | Bulk common update | Compatible rows, conditional state/version, per-row readback. |
| Correct | Existing edit/manual path | Explicit reason/actor/version and provider guard. |
| Delete/Void | Source-specific delete or generic delete | Separate draft delete, business void and provider correction. |
Rollback¶
- disable target command routes/actions;
- restore PHP writer selector;
- retain all committed MySQL rows/audit;
- do not replay create/close/correction;
- reconcile any request with unknown response by exact IDs/UUIDs.
Caller-zero before PHP removal¶
- transaction list/form JavaScript;
- all source create/delete buttons;
- close modal/actions;
- direct API callers;
- shared helper calls;
- scripts/tests/imports;
- report/file/provider consumers.
8. Wave BILL-W4 — AR Billing Confirm¶
Read-first prerequisites¶
- accepted
BILL-POL-060preview consistency; - active invoice uniqueness/version policy;
- correction policy;
- exact source/rate/preset/transaction-type field contract;
- target-role/API matrix.
Target transaction¶
For one confirm request, preserve the accepted all-items local atomicity unless policy intentionally changes it.
BEGIN
-> validate every candidate and source fingerprint
-> resolve customer/preset/rates/types
-> enforce active invoice uniqueness
-> insert or approved-version-rewrite each header/lines
-> record correction/version relation where applicable
-> optionally create QBO intent record without provider call
-> exact reread
COMMIT
Parity scenarios¶
- one candidate success;
- multiple candidate all-or-nothing success;
- one invalid candidate rolls back request;
- existing source AR conflict;
- existing unsynced container AR correction;
- existing synced row blocked;
- concurrent same booking/container confirm;
- response loss followed by exact reread.
Rollback¶
Resume PHP confirm only when:
- target writer is disabled;
- no target request is in-flight;
- current active invoice/version is known;
- QBO intent state is known;
- operator uses current rows, not a replayed preview.
9. Waves BILL-W5 And BILL-W6 — QBO¶
W5 shadow/intents¶
Introduce target concepts without sending provider effects:
QboInvoiceIntent
QboInvoiceAttempt
QboInvoiceReconciliation
Shadow mode may:
- build target payload;
- compute immutable group identity and payload hash;
- compare current PHP group/payload/result;
- search/read provider only if separately authorized and supported;
- never create an invoice.
W6 provider cutover¶
One effect intent chooses exactly one send owner.
sequenceDiagram
participant App as TypeScript Application
database DB
participant Worker
participant QBO
App->>DB: Commit local invoice + effect intent
Worker->>DB: Claim one intent/attempt
Worker->>QBO: Search/reconcile or create using intent identity
QBO-->>Worker: Provider result/unknown
Worker->>DB: Persist attempt and reconciliation
App->>DB: Project invoice delivery state
Required effect states¶
PENDING
CLAIMED
PROVIDER_ACCEPTED
SYNCED
FAILED_RETRYABLE
FAILED_FINAL
UNKNOWN_PROVIDER_RESULT
MANUAL_REVIEW
CANCELLED_BEFORE_ATTEMPT
Cutover rule¶
- current PHP
/qbo-syncsend disabled for target cohort; - worker is only provider-create owner;
- current UI may call a compatibility target command but does not call QBO directly;
SYNCINGcompatibility projection derives from active target attempt, not a second independent claim.
Rollback¶
- Stop worker from claiming new intents.
- Let or manually reconcile claimed/in-flight attempts.
- Do not route unresolved intents to PHP until provider absence/known state is established.
- For new requests only, restore PHP sender if explicitly approved.
- Preserve target intent/attempt records for audit.
Caller-zero¶
- PHP QBO helper/client creation path;
- browser automatic qbo-sync call;
- manual qbo-sync calls;
- token refresh inside business route;
- direct QBO status writes;
- scripts/support procedures relying on raw
QBO_ERRORclaim token.
10. Waves BILL-W7 And BILL-W8 — Files¶
W7 object/link read and write¶
Target contracts:
UploadFileObject
LinkFileToTransaction
GetTransactionFiles
GetFileReadability
Initial storage remains current EFS/S3.
Identity/parity¶
| Concept | Current mapping | Target identity |
|---|---|---|
| Object | path/URL/storage/UUID in upload metadata and T_FILE rows |
file-object UUID + storage provider/key + content hash |
| Link | T_FILE.TABLE_NAME/TABLE_ID/TYPE |
independent link UUID + target entity UUID + object UUID + link type |
| Readability | generated download URL/object access | read/check result with timestamp/error classification |
| Sequence | current max/order | presentation ordering, not identity |
W8 unlink/cleanup¶
Commands:
UnlinkFileFromTransaction
EvaluateFileObjectCleanup
DeleteUnreferencedFileObject
ReconcileOrphanFileObject
Cleanup worker must never delete while:
- active links exist;
- legal/retention hold exists;
- link/reference inventory is unknown;
- storage result is unknown.
Rollback¶
- stop cleanup worker immediately;
- preserve objects and active links;
- restore current upload/link UI for new work;
- never reconstruct missing objects by copying a stale URL;
- reconcile any object/link unknown result before retry.
Caller-zero¶
- media upload consumers;
- generic
/filescallers; - transaction document registration;
- delete/type-update actions;
- direct path/URL consumers;
- BOL/Packing attachment readers;
- Wiki/file special consumers kept under their own capability.
11. Wave BILL-W9 — BOL Email¶
Target intent identity¶
intent UUID
+ tenant
+ transload UUID
+ recipient-set hash
+ subject/content version
+ attachment object UUID/hash set
Required sequence¶
operator reviews readiness
-> command commits EmailIntent and target/attachments
-> worker claims attempt
-> search/reconcile if prior unknown
-> send Gmail
-> persist message/thread ID
-> operator sees exact result
Parity¶
- same normal recipient semantics after removal of username override;
- same subject/reference;
- same optional scale PDF and active source files;
- same no-business-state rollback on mail failure;
- improved durable intent/result and unknown recovery.
Rollback¶
- stop new worker claims;
- reconcile claimed/in-flight sends;
- restore current endpoint only for newly created intent versions after explicit choice;
- do not replay an unresolved intent through PHP.
12. Wave BILL-W10 — Packing List Target-Part Email¶
Target hierarchy¶
PackingEmailBatch
-> EmailTarget CUSTOMER/INSPECTOR
-> EmailPart 1..N
-> EmailAttempt(s)
-> Provider reconciliation
Required parity¶
- booking/equipment source model;
- selected weight/reference options;
- selected targets;
- recipient resolution;
- generated body and attachment partition content;
- subject and part numbering;
- preserve successful target-parts after later failure.
Intent versioning¶
If source content, options, recipients or partitioning changes:
new batch version
Do not mix a regenerated part set with prior successful parts under the same immutable batch version.
Rollback¶
- stop new attempts;
- preserve all sent message IDs;
- current endpoint may send only a new intentionally versioned batch after unresolved old parts are reviewed;
- never replay full target automatically.
Caller-zero¶
- current booking email route;
- browser action;
- GmailSender direct call;
- attachment split/temp cleanup path;
- current response-only Results assumptions;
- admin override.
13. Wave BILL-W11 — Daily Composite Reconciliation¶
Target result¶
A React worklist shows each applicable child checkpoint without creating a universal business state.
Local transaction
Local container AR
QBO
File
BOL email
Packing target/parts
Possible human disposition:
VERIFIED
CARRIED
NOT_APPLICABLE
BLOCKED
UNKNOWN
If persisted, the disposition references exact child IDs/evidence/owner and remains non-authoritative over child state.
Parity¶
- every current applicable child remains visible;
- no provider/file/email completion inferred from local close;
- unresolved items show next owner and safe action;
- no action replay from the composite page without invoking the child command.
Rollback¶
Return to current manual cross-page review. Child data/effects remain unchanged.
14. Wave BILL-W12 — Legacy Retirement¶
Required caller inventory status¶
ACTIVE
COMPATIBILITY
TEST_ONLY
HISTORICAL
UNKNOWN
REMOVED_AND_VERIFIED
UNKNOWN blocks deletion.
Retirement families¶
- generic BMS transaction routes/helpers and table-mutation form;
- AR Billing PHP routes/helper/JS;
- direct QuickBooks client and request-path token refresh;
- shared file routes only where fully replaced and not consumed by other domains;
- BOL/Packing direct Gmail routes;
- old PHP pages and shared JS;
- configuration keys only after new owner and migration;
- documentation and Wiki application links.
Runtime evidence¶
- static search;
- route/caller telemetry;
- server access logs;
- provider/effect logs;
- scheduled jobs/scripts;
- bookmarks/Wiki links;
- target-role browser traffic;
- controlled compatibility-disable observation.
15. Wave BILL-W13 — PostgreSQL Later¶
P11 preserves the accepted TypeScript/MySQL contract.
Required parity:
- transaction/invoice UUID and active uniqueness;
- decimal precision/currency/rounding;
- soft-delete and invoice-version relation;
- conditional transitions and concurrency;
- QBO/file/email effect identities and attempts;
- JSON/preset mapping;
- file object/link reference integrity;
- target-part identity;
- indexes/query plans;
- active in-flight intent migration;
- failback representation.
Do not move provider sends during the DB cutover.
16. Stable Migration Scenario Catalog¶
Read parity¶
| ID | Scenario | Required evidence |
|---|---|---|
BILL-MIG-SCN-010 |
Generic transaction old/new list/detail parity | Same selected rows, lines, totals, statuses and identities. |
BILL-MIG-SCN-020 |
AR workbench parity | Candidate, warnings, totals, existing state. |
BILL-MIG-SCN-030 |
AR preview parity | Line source/qty/rate/amount/total. |
BILL-MIG-SCN-040 |
File list/readability parity | Object/link/read state. |
BILL-MIG-SCN-050 |
Billing close worklist | Correct applicable checkpoints and unresolved owner. |
Local writes¶
| ID | Scenario | Required evidence |
|---|---|---|
BILL-MIG-SCN-110 |
One source transaction create | One semantic result and no duplicate. |
BILL-MIG-SCN-120 |
Compatible multi-row close | Per-row conditional write/readback. |
BILL-MIG-SCN-130 |
Mixed-company close rejected | No row mutation. |
BILL-MIG-SCN-140 |
Close response loss | Exact reread; no blind reapply. |
BILL-MIG-SCN-150 |
AR confirm one/many | Accepted atomicity and active uniqueness. |
BILL-MIG-SCN-160 |
Concurrent AR confirm | One accepted active invoice/version outcome. |
BILL-MIG-SCN-170 |
Synced correction blocked | No raw local mutation. |
Effects¶
| ID | Scenario | Required evidence |
|---|---|---|
BILL-MIG-SCN-210 |
QBO normal delivery | Intent/attempt/provider/local reconciliation. |
BILL-MIG-SCN-220 |
QBO provider success/local response loss | Search/reconcile; no duplicate create. |
BILL-MIG-SCN-230 |
QBO stale claimed attempt | Safe disposition, no time-only resend. |
BILL-MIG-SCN-240 |
File object success/link failure | Targeted link recovery; no duplicate object. |
BILL-MIG-SCN-250 |
Shared object unlink | Object retained while another link exists. |
BILL-MIG-SCN-260 |
BOL unknown result | Sent/provider reconciliation before resend. |
BILL-MIG-SCN-270 |
Packing later part failure | Prior parts preserved; only unresolved part eligible. |
BILL-MIG-SCN-280 |
Gmail send response loss | Provider message reconciliation. |
Cutover/rollback¶
| ID | Scenario | Required evidence |
|---|---|---|
BILL-MIG-SCN-310 |
One-writer selector | One command/effect owner per cohort. |
BILL-MIG-SCN-320 |
Rollback after committed local write | PHP resumes from current state; no replay. |
BILL-MIG-SCN-330 |
Rollback with provider attempt in-flight | Attempts reconciled before alternate sender. |
BILL-MIG-SCN-340 |
Compatibility disable observation | No unknown caller; support path remains. |
BILL-MIG-SCN-350 |
Caller-zero | All callers classified; unknown zero. |
17. Wave Status Ledger¶
| Wave | Status | Activation decision | Starting revision | Writer/effect selector | Evidence | Rollback result | Caller-zero |
|---|---|---|---|---|---|---|---|
BILL-W0 |
NOT_STARTED |
||||||
BILL-W1 |
NOT_STARTED |
||||||
BILL-W2 |
NOT_STARTED |
||||||
BILL-W3 |
NOT_STARTED |
||||||
BILL-W4 |
NOT_STARTED |
||||||
BILL-W5 |
NOT_STARTED |
||||||
BILL-W6 |
NOT_STARTED |
||||||
BILL-W7 |
NOT_STARTED |
||||||
BILL-W8 |
NOT_STARTED |
||||||
BILL-W9 |
NOT_STARTED |
||||||
BILL-W10 |
NOT_STARTED |
||||||
BILL-W11 |
NOT_STARTED |
||||||
BILL-W12 |
NOT_STARTED |
||||||
BILL-W13 |
NOT_STARTED |
Documentation completion does not advance a wave status.
---¶
Source:
docs/processes/CTC_BILLING_QBO_FILES_EMAIL_PARITY_AND_CUTOVER_MATRIX.md— ctc repository · This page is an English translation of the source document. Identifiers, file paths and code symbols are unchanged.