Forensic review · NetSuite TD3016323
Transaction lineage, user activity, change history, and anomaly screening across twelve months of posting activity, with the one finding that reframes all the others.
Scope: Standard Review. Posting transactions dated in the trailing twelve months (3,361 documents), the system notes recorded against transactions in the same window (1,022 notes), the login audit trail (7,042 events), and the employee master. The account holds 2.09 million system notes in total; 1.68 million of them belong to one custom record type and were excluded as out of scope for a transaction investigation.
The investigation produced one finding that governs every other. The entire twelve-month transaction history was entered into the account between September 2 and September 30, 2026: 2,783 of 3,361 documents (83%) were created more than 30 days after their transaction date, the median gap is 125 days, and 172 documents were created before the date they carry. This is a bulk load, not organic activity. Every timing test in the framework, after-hours entry, weekend entry, sequence analysis, must be read in that light: the patterns are real, but they describe the load, not the business.
Two findings survive that caveat. First, 98.3% of transactions carry no creator at all, so user attribution is impossible for the population; the system notes attribute the load to two user identities, both belonging to the account owner, working mostly through a Suitelet. Second, 45 pairs of transactions share a type, a counterparty, an amount, and a date within seven days, and two of them, an invoice pair and a payment pair, are same-day duplicates that deserve a look.
Based on: creation timestamp against transaction date. The transaction dates run from September 2025 to September 2026, one year of business activity. The creation timestamps run from September 2 to September 30, 2026, four weeks. Everything the account shows as a year of trading was keyed in a month.
| Type | Documents | After hours | Weekend | Round amounts | Median days after date | Entered 30+ days late |
|---|---|---|---|---|---|---|
| VendBill | 552 | 209 | 49 | 10 | 120 | 471 |
| VendPymt | 543 | 210 | 40 | 5 | 117 | 457 |
| CashSale | 542 | 541 | 355 | 0 | 154 | 462 |
| ItemRcpt | 410 | 260 | 40 | 1 | 112 | 336 |
| CustInvc | 405 | 137 | 240 | 0 | 149 | 343 |
| CustPymt | 394 | 142 | 239 | 2 | 148 | 315 |
| ItemShip | 389 | 202 | 244 | 0 | 150 | 322 |
| Journal | 60 | 28 | 11 | 0 | 62 | 38 |
| Deposit | 27 | 25 | 18 | 0 | 165 | 22 |
The lag is consistent across document types, which is what a scripted load looks like. Vendor bills and payments were entered in one pass, customer documents in another, with medians four weeks apart. Journals were entered last, with the shortest lag, and mostly in the first half of September.
The transaction table attributes only 56 of 3,361 documents to a user. The system notes are more complete: 1,022 notes on transactions in the window, 741 by the identity "Timothy Dietrich" and 278 by "Tim Dietrich", both belonging to the account owner. By context, 835 of the notes were written from a Suitelet, 120 from the user interface, and 64 through the REST API. The load was performed by a script, and the script's user is the owner.
Login audit, trailing twelve months. 7,042 events from 116 distinct IP addresses, 63 failures. The account owner accounts for 6,766 of them, and 5,663 of those are calls to the MCP endpoint, which is programmatic access by an AI tool, not a person at a keyboard. Six other named users logged in during the year. The failures are token expiries (18) and a handful of wrong passwords; one wrong second factor. Nothing in the login trail suggests unauthorized access.
| User | Login events |
|---|---|
| Tim Dietrich | 6,766 |
| Timothy Dietrich | 139 |
| Partner Admin 1 | 51 |
| (token) | 26 |
| Kathryn Glass | 24 |
| Jacob Bailey | 19 |
| Ben Morgan | 12 |
| Nick Singh | 4 |
| Ann Traynor | 1 |
Access review. 51 employee records, 20 inactive, 21 with NetSuite access. No inactive employee retains access. However, 13 employees with access have no login event in twelve months. Those are dormant accounts under the prompt's definition and are listed for review: Abby Kwan, Conner Avery, Dean Nolan, Emma Richards, Frank Davenport, Jeff Shipit, Joel Williams, Larry Nelson, Melissa Seaver, Molly Williams, Rick Ventz, Stella James, Sylvia Belanger.
125 documents were modified on a day after their creation, 3.7% of the population. The system notes on journal entries, the highest-risk document type, total 29 notes across 10 journals, all from May 2026, and all of them creation events through the REST API or a Suitelet. There are no field-level edits to journals in the window. That is either good news or evidence that journals are created complete by script and never touched, which for this account is the same thing.
The prompt's change-analysis block looks for override actions and deletions. The system notes in scope contain no approval overrides, because the account runs no approval workflow on the document types examined, and the deleted-record log was not in scope for this review.
1,786 documents (53%) were created outside 08:00 to 18:00, and 1,239 (37%) on a weekend. Under the prompt's thresholds that is "extensive" after-hours activity and would rate high risk. It does not here. The hour histogram below shows the load running in sessions at 03:00 to 07:00 and 15:00 to 17:00, and the weekday chart shows Wednesday and Saturday as the two busiest days. Those are the hours a person ran a loading script, not the hours a business enters invoices.
18 documents (0.5%) are exact multiples of $1,000. That is well under the 5% low-risk threshold. The largest is a $31,000 vendor bill from Generation N; the rest are small vendor bills and payments to Bedline, Crown Equipment, and Flexsteel. None warrants follow-up on amount alone.
The prompt's sequential test compares each document with the previous one of the same type. Applied as a duplicate screen (same type, same counterparty, same amount, dates within seven days), it returns 45 candidates. Most are retail cash sales for the same customer at the same price a few days apart, which is ordinary repeat purchasing. Two are not ordinary and are listed first below.
| Type | Counterparty | Amount | Documents | Dates |
|---|---|---|---|---|
| VendPymt | Generation N | $33,700.00 | 00000005/1-12102024-181841 / 00000005/1 | 3/1/2026 / 3/1/2026 |
| CustInvc | Macgruber Incorporated | $16,884.00 | INV762 / INV763 | 8/27/2026 / 8/27/2026 |
| ItemRcpt | Broyhill | $2,780.00 | IR1092 / IR1097 | 8/7/2026 / 8/12/2026 |
| ItemRcpt | Broyhill | $2,780.00 | IR1119 / IR1122 | 9/6/2026 / 9/7/2026 |
| VendBill | Broyhill | $2,780.00 | None / None | 8/9/2026 / 8/14/2026 |
| VendBill | Broyhill | $2,780.00 | None / None | 9/9/2026 / 9/10/2026 |
| VendPymt | Broyhill | $2,780.00 | 980 / 983 | 8/12/2026 / 8/17/2026 |
| VendPymt | Broyhill | $2,780.00 | 1000 / 1001 | 9/13/2026 / 9/14/2026 |
| ItemRcpt | Hestra | $2,600.00 | IR820 / IR823 | 5/11/2026 / 5/11/2026 |
| VendBill | Hestra | $2,600.00 | None / None | 5/12/2026 / 5/12/2026 |
Every figure above is reproducible from the queries in the appendix. Evidence for the bulk-load finding is the distribution of creation timestamps (3,353 in September 2026, 8 in October 2026, none earlier) against transaction dates spanning twelve months. Evidence for the attribution finding is the creator field, null on 3,305 rows, cross-referenced with the system note author on 1,022 notes. Evidence for the duplicate candidates is the document pairs listed, with internal ids retained in the data extract.
| ID | Type | Name | Handle | Scope | Used for | Complete |
|---|---|---|---|---|---|---|
| DL-001 | SuiteQL | Posting transactions | transaction (posting = T) | Trailing 12 months, 3,361 rows | Population, timing, amounts, duplicates | Yes |
| DL-002 | SuiteQL | Creation timestamps | transaction, TO_CHAR(createddate, HH24:MI) | Same population plus all journals | Hour and weekday analysis | Yes |
| DL-003 | SuiteQL | System notes on transactions | systemnote, recordtypeid = -30 | Trailing 12 months, 1,022 notes | Attribution, context, change review | Yes |
| DL-004 | SuiteQL | Login audit | loginaudit | Trailing 12 months, 7,042 events | Access patterns | Yes |
| DL-005 | SuiteQL | Employees | employee | 51 records | Access review | Yes, no last-login field |
Adaptations from the prompt's templates: the modification-history query joins system notes to transactions by recordtypeid = -30 and recordid, because systemnote.record holds a display name rather than an id; the JSON returned for createddate carries the date only, so the hour was fetched with TO_CHAR(createddate, 'HH24:MI'); transaction.subsidiary is not exposed, so no subsidiary filter was applied; employee.lastlogindate is not exposed, so dormancy was measured from the login audit instead; the sequential-analysis window function was replaced by a duplicate screen computed in code.
SELECT t.id, t.type, t.tranid, t.trandate, t.createddate, BUILTIN.DF(t.createdby), t.createdby, t.foreigntotal, BUILTIN.DF(t.entity), t.memo, t.lastmodifieddate FROM transaction t WHERE t.posting = 'T' AND t.trandate >= ADD_MONTHS(SYSDATE, -12) SELECT id, type, TO_CHAR(createddate, 'YYYY-MM-DD HH24:MI'), TO_CHAR(lastmodifieddate, 'YYYY-MM-DD HH24:MI'), TO_CHAR(createddate, 'DY') FROM transaction WHERE type = 'Journal' OR (posting = 'T' AND trandate >= ADD_MONTHS(SYSDATE, -12)) SELECT sn.field, sn.type, sn.context, sn.name, BUILTIN.DF(sn.name), COUNT(*), MIN(sn.date), MAX(sn.date) FROM systemnote sn WHERE sn.recordtypeid = -30 AND sn.date >= ADD_MONTHS(SYSDATE, -12) GROUP BY sn.field, sn.type, sn.context, sn.name, BUILTIN.DF(sn.name) SELECT sn.recordid, sn.record, sn.date, BUILTIN.DF(sn.name), sn.field, sn.oldvalue, sn.newvalue, sn.type, sn.context FROM systemnote sn WHERE sn.recordtypeid = -30 AND sn.record LIKE 'Journal%' AND sn.date >= ADD_MONTHS(SYSDATE, -12) SELECT BUILTIN.DF(la.user), la.status, la.detail, la.ipaddress, la.requesturi, COUNT(*), MIN(la.date), MAX(la.date) FROM loginaudit la WHERE la.date >= ADD_MONTHS(SYSDATE, -12) GROUP BY BUILTIN.DF(la.user), la.status, la.detail, la.ipaddress, la.requesturi SELECT e.id, e.entityid, e.isinactive, e.giveaccess, BUILTIN.DF(e.department), e.hiredate, e.releasedate FROM employee e
| Assumption | Category | Rationale | Sensitivity | Impact if wrong |
|---|---|---|---|---|
| Creation timestamp records when a document was entered | Data | System-maintained field | High | The bulk-load finding; the October timestamps already cast doubt |
| System note author is the actual actor | Data | System attribution | High | Attribution of the load |
| After hours = before 08:00 or from 18:00, account time zone | Business logic | Prompt definition | Low | After-hours counts |
| Duplicate = same type, counterparty, amount, within 7 days | Method | Conservative screen | Medium | Candidate list; requires human confirmation |
| Custom-record system notes out of scope | Method | 1.68M notes on one custom record type; not transactions | Low | None for transaction findings |
| Test | Objective | Result |
|---|---|---|
| G1-001 | Trail completeness | Qualified system notes cover the load; the transaction creator field does not |
| G1-002 | Timestamp accuracy | Fail 8 creation timestamps postdate the investigation |
| G1-003 | User attribution | Fail 98.3% of documents have no creator; attribution rests on system notes |
| G2-001 | Pattern detection reasonable | Pass patterns match a scripted load; reviewed manually |
| G2-002 | Timeline sequence | Pass creation order consistent with document type batches |
Confidence: 95% that the twelve-month history was bulk-loaded in September 2026 (timestamp distribution, system note context, uniform lag); 90% that the two same-day pairs are duplicates worth reviewing; low confidence in any conclusion about user behavior, because the population contains almost no organic activity.