toga-ai 1.0.1077 → 1.0.1079
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/knowledge/1.0/apps/test/INDEX.md +1 -0
- package/knowledge/1.0/apps/test/workflows/retiring-unused-legacy-elastic-beanstalk-environments.md +70 -0
- package/knowledge/2.0/apps/_underscore/INDEX.md +3 -0
- package/knowledge/2.0/apps/_underscore/features/contact-notes-files-types.md +1 -1
- package/knowledge/2.0/apps/_underscore/features/location-unit-department-notes-files.md +67 -0
- package/knowledge/2.0/apps/_underscore/features/note-record-authorship.md +4 -2
- package/knowledge/2.0/apps/_underscore/features/record-activity-timeline.md +5 -3
- package/knowledge/2.0/apps/_underscore/features/record-hard-delete.md +16 -2
- package/knowledge/2.0/apps/_underscore/features/service-request-links.md +43 -0
- package/knowledge/2.0/apps/_underscore/features/tableview-presets.md +41 -0
- package/knowledge/2.0/apps/api2/features/cross-client-data-retrieval.md +7 -1
- package/knowledge/2.0/apps/api2/features/v2-rest-query-contract.md +9 -2
- package/knowledge/INDEX.md +2 -2
- package/package.json +1 -1
|
@@ -19,3 +19,4 @@
|
|
|
19
19
|
| [TOGa 2.0 Client Onboarding Wizard (local tool)](features/toga2-onboarding-wizard.md) | Local browser wizard automating 2.0 client onboarding end-to-end (generates all onboarding SQL + consolidates dbchanges2 loose SQL); local-only, renders secrets |
|
|
20
20
|
| [TOGa 2.0 User Cross-Client Access SQL Generator](features/toga2-user-cross-client-access-sql.md) | 1.0 App_ script generating SQL to grant an existing 2.0 user cross-client access (Users_Roles grants); open when granting a home-client user into another client |
|
|
21
21
|
| [URL & Domain Markdown Document Builder](features/url-domain-markdown-document.md) | 1.0 App_ script building a markdown doc of our URLs/domains from the 2.0 API (/environments, /domains); open to regenerate the URL/domain reference. |
|
|
22
|
+
| [Finding and Retiring Unused Elastic Beanstalk Environments (legacy AWS account 502614707982)](workflows/retiring-unused-legacy-elastic-beanstalk-environments.md) | Runbook to prove an EB env in legacy account 502614707982 (us-west-2) is unused (DNS in two accounts + external, shared-ALB rules, CodePipeline) and tear it dow |
|
package/knowledge/1.0/apps/test/workflows/retiring-unused-legacy-elastic-beanstalk-environments.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Finding and Retiring Unused Elastic Beanstalk Environments (legacy AWS account 502614707982)
|
|
3
|
+
framework: "1.0"
|
|
4
|
+
repo: test
|
|
5
|
+
project: Test
|
|
6
|
+
client: shared
|
|
7
|
+
type: workflow
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-10-19
|
|
10
|
+
owners: [jcardinal]
|
|
11
|
+
files: []
|
|
12
|
+
related:
|
|
13
|
+
- ../features/create-elastic-beanstalk.md
|
|
14
|
+
- ../../togaview/workflows/route53-cross-account-zone-migration.md
|
|
15
|
+
- ../../../../2.0/apps/worker2/features/alb-target-group-auto-registration.md
|
|
16
|
+
- ../../../../2.0/apps/api2/workflows/codepipeline-codeconnections-deploy.md
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
Runbook to prove an EB env in legacy account 502614707982 (us-west-2) is unused (DNS in two accounts + external, shared-ALB rules, CodePipeline) and tear it down in safe order; also the legacy cost picture, what was retired (TRUE-82821), and open cost follow-ups.
|
|
20
|
+
|
|
21
|
+
## Summary
|
|
22
|
+
|
|
23
|
+
Use when cutting the legacy AWS bill or cleaning old envs. An env is **used** only if DNS or a queue reaches it — prove that before you terminate anything. Infrastructure only; no app repo changes. `test` is the home for team AWS tooling (see `create-elastic-beanstalk.md`).
|
|
24
|
+
|
|
25
|
+
**Cost picture (Sept 2026, ~$24.4k/mo):** RDS $9.8k, EC2 compute $3.5k + EC2-Other $1.1k, WAF $2.0k (was $558 in July), VPC $1.9k, ELB $1.5k, Bedrock Claude ~$1.2k (≈$3.5k by mid-Oct, rising). No CloudFront in this account.
|
|
26
|
+
|
|
27
|
+
## Steps
|
|
28
|
+
|
|
29
|
+
1. **Collect all DNS.** Route 53 lives in BOTH accounts:
|
|
30
|
+
- legacy 502614707982: `agilantsolutions.com`, `truesolutions.com`, `togasuite.com`, `truenetworksolutions.com`
|
|
31
|
+
- prod 654654170868: `togacommerce.com`, `togaiq.com`, `togatech.com`, `togaretail.com`, `togadesk.com`, `togasupply.com`, `togahub.com`, `togatechnology.com`, `togaview.com`
|
|
32
|
+
- **Outside AWS** (`asisystem.com`, `goagilant.com`): ask the developer for a DNS export. Never call an env unused without it.
|
|
33
|
+
2. **Direct use.** A record points at the env's EB CNAME, its load-balancer DNS, or its single-instance IP → used.
|
|
34
|
+
3. **Shared-ALB use.** A record points at a shared ALB (today only `true-alb-beta`) → evaluate listener rules **by priority**, with ALB host wildcards (`*` can sit mid-name, e.g. `forecast.*.togatech.com`). The matching rule's target group name = the EB env name (team convention). A default-rule match is not "use" unless intended.
|
|
35
|
+
4. **Worker-tier envs** have no DNS — judge by their SQS queues.
|
|
36
|
+
5. **CodePipeline.** Deploy actions name the EB env. All EB actions target removed envs → delete the pipeline. Some still live → remove only the dead action (and any now-empty approval stage).
|
|
37
|
+
6. **Tear down in this order:**
|
|
38
|
+
1. delete/edit pipelines
|
|
39
|
+
2. terminate EB envs
|
|
40
|
+
3. delete ALB listener rules (a default rule pointing at a removed TG → change to fixed-response 404)
|
|
41
|
+
4. delete target groups
|
|
42
|
+
5. delete DNS records
|
|
43
|
+
6. delete a shared ALB once no rule and no DNS uses it
|
|
44
|
+
7. **Clean dangling CNAMEs** to `*.elasticbeanstalk.com` names that no longer exist, in every zone incl. external ones.
|
|
45
|
+
|
|
46
|
+
## Gotchas
|
|
47
|
+
|
|
48
|
+
- **EB terminate leaves shared-ALB pieces behind.** Manually created target groups and listener rules on a shared ALB survive termination — delete them yourself (step 6).
|
|
49
|
+
- **Dangling EB CNAME = subdomain-takeover risk.** Anyone can claim a freed `*.elasticbeanstalk.com` prefix. 4 were found in `asisystem.com` (removed 2026-10).
|
|
50
|
+
- **Claude auto mode blocks destructive AWS deletes** (`codepipeline delete-pipeline`, `elbv2 delete-load-balancer`) even with `Bash(*)`. Allow rules in `settings.local.json` (`Bash(aws codepipeline:*)`, `Bash(aws elasticbeanstalk:*)`, `Bash(aws elbv2:*)`, `Bash(aws route53:*)`) unblock most; `delete-load-balancer` stays blocked — give that command to the developer. The `start-gate` hook blocks Claude from editing `settings*.json`; the developer edits it.
|
|
51
|
+
- **Externally referenced envs look dead from AWS.** `asi-api-prod` (`api.asisystem.com`) and `agilant-vision-prod` (`vision.asisystem.com`) have no Route 53 record but are live.
|
|
52
|
+
|
|
53
|
+
## Retired 2026-10-15 → 10-19 (TRUE-82821, approved by jcardinal)
|
|
54
|
+
|
|
55
|
+
- **EB envs (24):** agilant-forecast-alpha, agilant-goagilant-alpha, agilant-store-alpha, agilant-store-beta, true-togacommerce-alpha/-beta/-gamma, agilant-vision-alpha, agilant-fujitsu-prod, agilant-goagilant-prod, cloudsupporthq-togadesk-prod, true-toga-commmerce-beta, true-togadesk-beta, true-togadesk-production, true-togahub-production, true-vision-alpha, agilant-api-alpha, agilant-forecast-beta, agilant-forecast-prod, agilant-toga-alpha, agilant-togadesk-alpha, agilant-togaview-alpha, agilant-worker-alpha, true-api-beta.
|
|
56
|
+
- **CodePipelines:** 38 deleted (18 already pointed at missing envs); `ITAD-Production` and `TOGaDesk-Production` edited to drop dead actions; 29 remain.
|
|
57
|
+
- **Shared ALBs:** `true-alb-alpha`, `true-alb-gamma` deleted. `true-alb-beta` remains (default rule → `agilant-vision-beta`).
|
|
58
|
+
- **DNS:** tools.beta / vision.alpha / tools.alpha / api-alpha / api.alpha `agilantsolutions.com`; `forecast.togatech.com`, `forecast.beta.togatech.com`; `cxml.beta.togahub.com`, `api.client.togahub.com`; all `*.alpha.togaview.com`, `*.alpha.togadesk.com`; `toga.alpha` / `togadesk.alpha.togatech.com`.
|
|
59
|
+
- **RDS Aurora (no final snapshot):** alpha1-cluster, sprint1-cluster, ui1-cluster, doa-client-writer. Remaining: beta1, demo1, gamma1, gamma, hotfix1, prod, production-logs, stage1.
|
|
60
|
+
- **Kept:** worker envs `agilant-worker`, `agilant-worker-beta`; `asi-api-prod`, `agilant-vision-prod`.
|
|
61
|
+
|
|
62
|
+
## Open follow-ups
|
|
63
|
+
|
|
64
|
+
1. WAF cost ~4x since July — not investigated.
|
|
65
|
+
2. Bedrock Claude spend rising month over month — find the caller.
|
|
66
|
+
3. Review the 8 remaining RDS clusters (largest cost line).
|
|
67
|
+
4. No AWS Budgets / Cost Anomaly alerts set up on the legacy account.
|
|
68
|
+
|
|
69
|
+
## Change history
|
|
70
|
+
- 2026-10-19 — Created from TRUE-82821 legacy cost cleanup: unused-env checks, teardown order, retired list, open follow-ups (jcardinal)
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
| [Global search (GET /records/search — tiered, per-client, data-configured fields)](features/global-search.md) | Platform (all 2.0 apps) header search across record types; open when making a field searchable, tuning ranking, or a search is slow or misses results. |
|
|
39
39
|
| [ItemClasses / _Model_Client_ItemClass — who actually uses it (and why it is not free)](features/item-classification-itemclasses.md) | `ItemClasses` is a near-unused per-client lookup that 2 of 36 clients already repurpose (Northwell service categories, Prudential device tiers); open before reu |
|
|
40
40
|
| [Item-Fulfillment Stage Lifecycle (picked/packed/shipped) & Order Status](features/item-fulfillment-stage-lifecycle-and-order-status.md) | Item-fulfillment stage lifecycle (picked→packed→shipped) driving the calculated order `_status`, with per-client status policies; open when working order status |
|
|
41
|
+
| [Location, Unit (asset), Ticket Department — notes + files tables, LocationTypes icons](features/location-unit-department-notes-files.md) | Shared Client-DB notes/files child tables for Locations, Units (assets) and TicketDepartments, plus LocationTypes icon columns; open before adding notes/files t |
|
|
41
42
|
| [DB-free unit testing for _underscore model interceptors](features/model-interceptor-unit-testing.md) | DB-free unit-test scaffold for `_underscore` model interceptor/validation logic (stub the persistence base, reflect into privates); open when testing a `prePost |
|
|
42
43
|
| [_Model magic-field access (__get without __isset)](features/model-magic-field-access.md) | `_Model` has `__get` but NO `__isset`, so `isset()`/`??`/`empty()` on a magic DB field are unreliable or false; open before probing an optional model field or d |
|
|
43
44
|
| [_Model::save() parent FK cascade — stored-SQL-field recompute deadlocks](features/model-save-parent-cascade-stored-field-deadlock.md) | Why a child insert deadlocks (MySQL 1213): `_Model::save()` re-saves the parent to recompute stored SQL fields; open when a child-insert path deadlocks or befor |
|
|
@@ -61,6 +62,7 @@
|
|
|
61
62
|
| [Sales-order \"PO Number\" sourcing — one surface element, `_purchaseOrders`, tenant SQL underneath](features/sales-order-po-number-sourcing.md) | How the SO modal "PO Number" field is sourced (one surface element → `_purchaseOrders` calc field → tenant SQL); open before touching PO-number display, the ups |
|
|
62
63
|
| [SO↔PO and TO↔PO bridge tables are TWO tables in OPPOSITE directions (upstream vs downstream)](features/sales-order-purchase-order-bridge-direction.md) | The two SO↔PO (and two TO↔PO) bridge tables mean opposite things (upstream = customer PO, downstream = vendor PO); open when an SO/TO↔PO query returns an empty |
|
|
63
64
|
| [Per-client sales-order status filter (Surface FILTER_SET → table meta `filterOptions`)](features/sales-order-status-filter-surface.md) | Per-client status-filter dropdown on the sales-orders table, driven by a Surface `FILTER_SET`; open when the offered statuses are wrong for a tenant or when onb |
|
|
65
|
+
| [Service request links (ServiceRequests_Tickets, ServiceRequests_ServiceRequests bridges)](features/service-request-links.md) | Many-to-many links from a service request to tickets and to other service requests; open before linking SRs, reading `_linkCount`, or touching the old `ServiceR |
|
|
64
66
|
| [Shipping Carriers & Carrier Account Numbers (records, matching, duplication, deletion)](features/shipping-carriers-and-accounts.md) | Per-client `ShippingCarriers` / `ShippingCarrierAccountNumbers` model, how the syncs match/create carrier rows, and the duplication + blank-carrier + pagination |
|
|
65
67
|
| [Ticket SLA engine (_Component_Sla) — two clocks, per-stage effects, client switch + operator recompute](features/sla-engine.md) | How 2.0 ticket SLA due times, pauses and the per-client switch are computed and written (`_Component_Sla`); open when an SLA countdown is wrong, a stage does no |
|
|
66
68
|
| [_String helpers — ASCII-safe HTML entity encoding (and the parseBetween trap)](features/string-html-entity-helpers.md) | `_String` static string utilities: use `encodeToAsciiHtmlEntities` for any dynamic text going into a 2.0 email; open when escaping email text or parsing substri |
|
|
@@ -69,6 +71,7 @@
|
|
|
69
71
|
| [Surface Resolver (_Model_Core_Surface::resolve — replaces Page::meta)](features/surface-resolver.md) | Runtime for the platform Surface UI layer (`_Model_Core_Surface::resolve`/`metaGroup`, replaces `Page::meta`); open for surface resolution, the override cascade |
|
|
70
72
|
| [Table-View Hyperlink Columns (meta → ACL → computed URL → render)](features/tableview-hyperlink-columns.md) | How a 2.0 table-view column renders its value as a clickable link (`hyperlinkRecordFieldId` → ACL field-read → computed URL → render); open when a configured hy |
|
|
71
73
|
| [TableView joins (TableViewJoins → SQL) — aliasing, chained multi-hop joins, ACL](features/tableview-joins.md) | How `TableViewJoins` rows become a view's join SQL — aliasing, chained multi-hop joins, ACL gating, and the three ways a view breaks; open before adding/rebasin |
|
|
74
|
+
| [Table view presets (saved views — TableViewPresets.config whitelist)](features/tableview-presets.md) | A user's saved table view stored as one validated JSON `config`; open before adding anything new to what a saved view remembers. |
|
|
72
75
|
| [2.0 Ticket status (`_status`) is derived from the stage's linked TicketStatuses row](features/ticket-status-from-stage.md) | How a 2.0 ticket's `_status` is computed (stage → TicketStatuses link, else `in-progress` / `new-ticket`); open when a ticket shows the wrong status or a status |
|
|
73
76
|
| [Talos Gateway Client (_Component_Api_Togaiq) — AI generate/translate from 2.0](features/togaiq-gateway-client.md) | The 2.0 client for the Talos AI gateway (`_Component_Api_Togaiq`); open to call an LLM (generate/translate) from a 2.0 model/interceptor, or to debug "translati |
|
|
74
77
|
| [Tracking-Number Bridge Migration (ASN / Item Fulfillment / Item Receipt)](features/tracking-number-bridges.md) | How tracking numbers moved from scalar FK columns to `*_TrackingNumbers` bridge tables across ASN/IF/IR; open before writing/reading tracking, choosing which br |
|
|
@@ -64,7 +64,7 @@ Added 2026-10-17 (TRUE-82871, built for TOGa Desk, usable by any app). Copies th
|
|
|
64
64
|
could delete a Files row a contact still uses.
|
|
65
65
|
- **Client schemas drift** (e.g. `Client_True.TransferOrders` has no `contactId`) — the delete map probes optional
|
|
66
66
|
columns with `columnExists()`.
|
|
67
|
-
- **
|
|
67
|
+
- **Saved views cannot be seeded** — see [table view presets](./tableview-presets.md).
|
|
68
68
|
|
|
69
69
|
## Change history
|
|
70
70
|
- 2026-10-17 — Created: ContactTypes.slug + seeds, Contacts_Files, ContactNotes, contact activity root, contact delete (TRUE-82871). (jcardinal)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Location, Unit (asset), Ticket Department — notes + files tables, LocationTypes icons
|
|
3
|
+
framework: "2.0"
|
|
4
|
+
repo: _underscore
|
|
5
|
+
project: _Underscore
|
|
6
|
+
client: shared
|
|
7
|
+
type: feature
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-10-19
|
|
10
|
+
owners: [jcardinal]
|
|
11
|
+
files:
|
|
12
|
+
- _underscore/Model/Client/LocationNote.php
|
|
13
|
+
- _underscore/Model/Client/Locations/File.php
|
|
14
|
+
- _underscore/Model/Client/UnitInternalNote.php
|
|
15
|
+
- _underscore/Model/Client/Units/File.php
|
|
16
|
+
- _underscore/Model/Client/TicketDepartmentNote.php
|
|
17
|
+
- _underscore/Model/Client/TicketDepartments/File.php
|
|
18
|
+
- dbchanges2/Client/2026-10-18l - TRUE-82911 LocationUnitNotesFiles.sql
|
|
19
|
+
- dbchanges2/Client/2026-10-19a - TRUE-82911 DepartmentNotesFiles.sql
|
|
20
|
+
- dbchanges2/Client/2026-10-19b - TRUE-82911 LocationTypeIcons.sql
|
|
21
|
+
related:
|
|
22
|
+
- ./customer-locations-files-notes.md
|
|
23
|
+
- ./contact-notes-files-types.md
|
|
24
|
+
- ./note-record-authorship.md
|
|
25
|
+
- ./record-hard-delete.md
|
|
26
|
+
- ./record-activity-timeline.md
|
|
27
|
+
---
|
|
28
|
+
Shared Client-DB notes/files child tables for Locations, Units (assets) and TicketDepartments, plus LocationTypes icon columns; open before adding notes/files to one of these records or touching `UnitNotes`.
|
|
29
|
+
|
|
30
|
+
## Summary
|
|
31
|
+
|
|
32
|
+
Added 2026-10-18/19 (TRUE-82911, built for TOGa Desk, usable by any app). Same shape as the Customer/Contact
|
|
33
|
+
pattern ([customer related records](./customer-locations-files-notes.md)) — read that doc for the shared shape.
|
|
34
|
+
|
|
35
|
+
| Table | Shape | Core Records |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| `LocationNotes` | write-once note, server-stamped `authorUserId` | 414 `location-notes` |
|
|
38
|
+
| `Locations_Files` | file link (create / read / delete, no update) | 415 `location-files` |
|
|
39
|
+
| `Units_Files` | file link | 416 `unit-files` |
|
|
40
|
+
| `UnitInternalNotes` | write-once note, server-stamped author | 417 `unit-internal-notes` |
|
|
41
|
+
| `TicketDepartmentNotes` | write-once note, server-stamped author | 420 `ticket-department-notes` |
|
|
42
|
+
| `TicketDepartments_Files` | file link | 421 `ticket-department-files` |
|
|
43
|
+
| `LocationTypes.iconToken` / `iconWeightToken` | nullable `VARCHAR(64)` / `VARCHAR(32)` | RecordFields 3104-3105 |
|
|
44
|
+
|
|
45
|
+
RecordFields 3062-3105 cover all of the above. SQL: `Client/2026-10-18l`, `2026-10-19a`, `2026-10-19b` (+ Core
|
|
46
|
+
`2026-10-18s`, `2026-10-19c`, `2026-10-19d`).
|
|
47
|
+
|
|
48
|
+
## How it works
|
|
49
|
+
|
|
50
|
+
- **Notes:** author stamped in `save()` from `_Model::getRequestUserId()`; no client user → 400; updates refused
|
|
51
|
+
([note authorship](./note-record-authorship.md)).
|
|
52
|
+
- **Files:** create / read / delete only. Each `*_Files` table is in `_Component_RecordDelete::FILE_REFERENCE_TABLES`.
|
|
53
|
+
- **Delete:** Locations (Records 11), Units (31), TicketDepartments (106) purge their notes + file links on a normal
|
|
54
|
+
table `DELETE` ([record hard delete](./record-hard-delete.md)).
|
|
55
|
+
- **Activity:** roots `locations` → `location-activity`, `ticket-departments` → `department-activity`; the three
|
|
56
|
+
note routes are in `CREATE_HIDDEN_ROUTES` ([record activity timeline](./record-activity-timeline.md)).
|
|
57
|
+
- **LocationTypes icons:** null = front end shows a pin. Production seed sets Shipping = `truck`,
|
|
58
|
+
Warehouse = `warehouse` only where null.
|
|
59
|
+
|
|
60
|
+
## Gotchas
|
|
61
|
+
|
|
62
|
+
- **Asset (Unit) notes from a user go in `UnitInternalNotes`, never `UnitNotes`.** `UnitNotes` holds typed condition
|
|
63
|
+
notes: toga2-supply reads them by position (`unitNotes[0]`, `[1]`) and the BofA import writes them with no
|
|
64
|
+
signed-in user, so an author-stamped `save()` there would break that import (cto agreed, 2026-10-18).
|
|
65
|
+
|
|
66
|
+
## Change history
|
|
67
|
+
- 2026-10-19 — Created: Location / Unit / TicketDepartment notes + files, LocationTypes icon columns (TRUE-82911). (jcardinal)
|
|
@@ -6,7 +6,7 @@ project: _Underscore
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-10-
|
|
9
|
+
updated: 2026-10-19
|
|
10
10
|
owners: [apeterson, jcardinal]
|
|
11
11
|
files:
|
|
12
12
|
- _underscore/Model/Client/SalesOrderNote.php
|
|
@@ -64,10 +64,12 @@ Before building anything that shows or filters by note author:
|
|
|
64
64
|
|
|
65
65
|
- **`contactId` on a `*Notes` model is an unwritten FK — treat it as always NULL.** Seven models, zero writers.
|
|
66
66
|
- **A notes list UI has no author to show.** Design for it, or the field silently renders blank for every row.
|
|
67
|
-
- **Exception — server-stamped author:** `CaseNotes`, `CustomerNotes`, `ContactNotes`, `IssuerNotes`, `CertificationNotes`, `AttributeNotes`, `UserNotes` carry `authorUserId`, stamped in `::save()` from `_Model::getRequestUserId()` (write-once). Copy that pattern for the real fix. The `save()` body is now copied
|
|
67
|
+
- **Exception — server-stamped author:** `CaseNotes`, `CustomerNotes`, `ContactNotes`, `IssuerNotes`, `CertificationNotes`, `AttributeNotes`, `UserNotes`, `LocationNotes`, `UnitInternalNotes`, `TicketDepartmentNotes` carry `authorUserId`, stamped in `::save()` from `_Model::getRequestUserId()` (write-once). Copy that pattern for the real fix. The `save()` body is now copied 10 times — **consolidation debt:** move it to a shared trait/base before adding another. See [Case status + stage gate](./case-status-and-stage-gate.md), [Customer related records](./customer-locations-files-notes.md), [Contact related records](./contact-notes-files-types.md), [Location / unit / department notes](./location-unit-department-notes-files.md).
|
|
68
|
+
- **Do not add author stamping to `UnitNotes`** — the BofA import writes it with no signed-in user and toga2-supply reads it by position. User-written asset notes use `UnitInternalNotes` ([why](./location-unit-department-notes-files.md#gotchas)).
|
|
68
69
|
- **`dtStamp` is `FIELD_DATETIME_CREATED`** — stamped by the ORM on insert, the only provenance a note actually carries.
|
|
69
70
|
|
|
70
71
|
## Change history
|
|
72
|
+
- 2026-10-19 — LocationNotes, UnitInternalNotes, TicketDepartmentNotes added (10 copies of save()); UnitNotes stays author-less (TRUE-82911). (jcardinal)
|
|
71
73
|
- 2026-10-17 — UserNotes added; seven author-stamped note models now copy one save() body (TRUE-82872). (jcardinal)
|
|
72
74
|
- 2026-10-17 — ContactNotes added as third server-stamped-author note model; save() body is a consolidation candidate (TRUE-82871). (jcardinal)
|
|
73
75
|
- 2026-10-17 — CustomerNotes added as a second server-stamped-author note model (TRUE-82870). (jcardinal)
|
|
@@ -6,7 +6,7 @@ project: _Underscore
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-10-
|
|
9
|
+
updated: 2026-10-19
|
|
10
10
|
owners: [jcardinal]
|
|
11
11
|
files:
|
|
12
12
|
- _underscore/Component/RecordActivity/RecordActivity.php
|
|
@@ -33,7 +33,7 @@ client `AclRecordScripts`. Data source: [record change audit log](record-change-
|
|
|
33
33
|
- **Roots** = `ROOT_ACTIVITY_SURFACE_SLUGS` (route → activity Surface slug): `tickets` →
|
|
34
34
|
`ticket-activity`, `units` → `asset-activity`, `cases` → `case-activity`, `service-requests` →
|
|
35
35
|
`service-request-activity`, `customers` → `customer-activity`, `contacts` → `contact-activity`,
|
|
36
|
-
`issuers`, `certifications`, `attributes`, `users` → `<singular>-activity`. Any other route → 400. **A new root = one map entry + its Surface
|
|
36
|
+
`locations` → `location-activity`, `ticket-departments` → `department-activity`, `issuers`, `certifications`, `attributes`, `users` → `<singular>-activity`. Any other route → 400. **A new root = one map entry + its Surface
|
|
37
37
|
(`dbchanges2` `Core/`).** Engine (`Source` reads Logs, `Reader` checks as the reader through api2)
|
|
38
38
|
is generic; no new client ACL needed for a new root.
|
|
39
39
|
- **Children:** `Logs.RecordParent`, level by level, max `Source::MAX_DEPTH` (3) levels and
|
|
@@ -47,7 +47,8 @@ client `AclRecordScripts`. Data source: [record change audit log](record-change-
|
|
|
47
47
|
4. FK values → `{uuid, label[, slug]}`, `{missing:true}`, or `{value:null}` — never a raw id.
|
|
48
48
|
- **CREATE rows of `CREATE_HIDDEN_ROUTES`** (`ticket-notes`, `ticket-note-files`, `unit-notes`,
|
|
49
49
|
`case-notes`, `service-request-notes`, `customer-notes`, `contact-notes`, `issuer-notes`,
|
|
50
|
-
`certification-notes`, `attribute-notes`, `user-notes`
|
|
50
|
+
`certification-notes`, `attribute-notes`, `user-notes`, `location-notes`, `unit-internal-notes`,
|
|
51
|
+
`ticket-department-notes`) are dropped — the host screen merges the notes feed.
|
|
51
52
|
Note edits/deletes still show.
|
|
52
53
|
- **Paging:** cursor = `Logs.Record` id; `nextCursor` null at the end. Scan bounded
|
|
53
54
|
(`MAX_SCAN_BATCHES` × `SCAN_BATCH_SIZE`); a page cut by the bound still returns a `nextCursor`.
|
|
@@ -74,6 +75,7 @@ client `AclRecordScripts`. Data source: [record change audit log](record-change-
|
|
|
74
75
|
`LOG_REDACTED_FIELD_NAMES`) and on read (`isRedactedLogField`).
|
|
75
76
|
|
|
76
77
|
## Change history
|
|
78
|
+
- 2026-10-19 — Added roots `locations`, `ticket-departments`; three new note routes hidden (TRUE-82911). (jcardinal)
|
|
77
79
|
- 2026-10-17 — Added root `users` + `user-notes`; listed `issuers` / `certifications` / `attributes` roots already in code (TRUE-82872). (jcardinal)
|
|
78
80
|
- 2026-10-17 — Added root `contacts` + `contact-notes` to `CREATE_HIDDEN_ROUTES` (TRUE-82871). (jcardinal)
|
|
79
81
|
- 2026-10-17 — Added root `customers` + `customer-notes` to `CREATE_HIDDEN_ROUTES` (TRUE-82870). (jcardinal)
|
|
@@ -6,7 +6,7 @@ project: _Underscore
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-10-
|
|
9
|
+
updated: 2026-10-19
|
|
10
10
|
owners: [jcardinal]
|
|
11
11
|
files:
|
|
12
12
|
- _underscore/Component/RecordDelete/RecordDelete.php
|
|
@@ -15,9 +15,11 @@ files:
|
|
|
15
15
|
- _underscore/Model/Client/Ticket.php
|
|
16
16
|
- _underscore/Model/Client/Case.php
|
|
17
17
|
- _underscore/Model/Client/ServiceRequest.php
|
|
18
|
+
- _underscore/Model/Client/Phase.php
|
|
18
19
|
related:
|
|
19
20
|
- ../../api2/features/api-payload-interceptors.md
|
|
20
21
|
- ./customer-locations-files-notes.md
|
|
22
|
+
- ./location-unit-department-notes-files.md
|
|
21
23
|
- ./record-activity-timeline.md
|
|
22
24
|
---
|
|
23
25
|
Map-driven hard delete of everything hanging off one record (block / detach / delete children / orphan Files); open before making a record deletable or adding a table with a Files FK.
|
|
@@ -27,7 +29,9 @@ Map-driven hard delete of everything hanging off one record (block / detach / de
|
|
|
27
29
|
`DELETE /v2/<route>/{uuid}` on an opted-in record runs a PRE DELETE interceptor that calls
|
|
28
30
|
`_Component_RecordDelete::purge(['model' => static::class, 'id' => $id])`. `purge()` cleans the related
|
|
29
31
|
rows from a map the model declares in `relatedRows()`; api2 then deletes the record row itself. Used by
|
|
30
|
-
Tickets, Cases, ServiceRequests, Customers, Contacts
|
|
32
|
+
Tickets, Cases, ServiceRequests, Customers, Contacts, Roles, Attributes, Locations, Units, TicketDepartments, Phases.
|
|
33
|
+
The class DocBlock is the full contract — read it before editing. **Make a record deletable through the normal table
|
|
34
|
+
`DELETE` + this interceptor — never a scripted API** (developer rule, 2026-10-19).
|
|
31
35
|
|
|
32
36
|
## How it works
|
|
33
37
|
|
|
@@ -53,6 +57,13 @@ Tickets, Cases, ServiceRequests, Customers, Contacts. The class DocBlock is the
|
|
|
53
57
|
ContactNotes, ContactAttempts, ContactMessagingOptIns, Campaigns_Contacts, Campaigns_MeetWithContacts,
|
|
54
58
|
Contacts_Tags, Contacts_Vendors, Contacts_Locations, Locations_Contacts, ContactAddresses / EmailAddresses /
|
|
55
59
|
PhoneNumbers. `preDelete` clears the contact's `primary*` pointers first (they and the children point at each other).
|
|
60
|
+
- **Location (Records 11) / Unit (31) / TicketDepartment (106) rule (`Core/2026-10-19a`, `2026-10-19e`):** delete
|
|
61
|
+
their notes (`LocationNotes`, `UnitInternalNotes`, `TicketDepartmentNotes`) and file links (`Locations_Files`,
|
|
62
|
+
`Units_Files`, `TicketDepartments_Files`, + orphan Files). Every other link (tickets etc.) is left to the DB FK —
|
|
63
|
+
see gotcha. Tables: [location / unit / department notes + files](./location-unit-department-notes-files.md).
|
|
64
|
+
- **Phase / stage rule (Records 359, `Core/2026-10-18q`):** blocked while any `Scopes.phaseId` uses it (no FK, so
|
|
65
|
+
the blocker is the only guard). `preDelete` returns a 400 naming the count + first 3 scopes; `purge()` re-checks
|
|
66
|
+
under the row lock.
|
|
56
67
|
- **Role rule (Records 274):** blocked by Users_Roles / Apis_Roles; ACL rows handled after `purge()` — full rule in
|
|
57
68
|
[ACL Capabilities § Role delete](acl-capabilities.md).
|
|
58
69
|
|
|
@@ -65,6 +76,8 @@ Tickets, Cases, ServiceRequests, Customers, Contacts. The class DocBlock is the
|
|
|
65
76
|
|
|
66
77
|
- **New table with a `fileId` FK → add it to `FILE_REFERENCE_TABLES`.** Missing it makes the Files DELETE fail on
|
|
67
78
|
the FK and roll back every delete that touches a shared file (loud, not silent).
|
|
79
|
+
- **A link not in the map is refused by its DB FK — as a 500, not a friendly 400.** Fine as a safety net; add a
|
|
80
|
+
`blockers` entry when the user needs a readable reason (Locations / Units / TicketDepartments still rely on FKs).
|
|
68
81
|
- **Client override of `relatedRows()` must merge `parent::relatedRows()` key by key;** a client `preDelete`
|
|
69
82
|
replaces the shared one and must call `parent::preDelete()`.
|
|
70
83
|
- **Use `$api->recordUuid ?? null`, never `isset($api->recordUuid)`** — `_Component` has `__get` but no `__isset`.
|
|
@@ -73,6 +86,7 @@ Tickets, Cases, ServiceRequests, Customers, Contacts. The class DocBlock is the
|
|
|
73
86
|
losing the link would lose meaning (orders, required FKs like `Contacts.customerId`).
|
|
74
87
|
|
|
75
88
|
## Change history
|
|
89
|
+
- 2026-10-19 — Locations, Units, TicketDepartments, Phases opted in; three `*_Files` tables added to FILE_REFERENCE_TABLES; table DELETE, never scripted API (TRUE-82911). (jcardinal)
|
|
76
90
|
- 2026-10-18 — Roles opted in (TRUE-82880). (jcardinal)
|
|
77
91
|
- 2026-10-17 — Contacts opted in (block / detach / cascade map, schema-drift probes); Contacts_Files added to FILE_REFERENCE_TABLES (TRUE-82871). (jcardinal)
|
|
78
92
|
- 2026-10-17 — Created; Customers opted in, Customers_Files added to FILE_REFERENCE_TABLES (TRUE-82870). (jcardinal)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Service request links (ServiceRequests_Tickets, ServiceRequests_ServiceRequests bridges)
|
|
3
|
+
framework: "2.0"
|
|
4
|
+
repo: _underscore
|
|
5
|
+
project: _Underscore
|
|
6
|
+
client: shared
|
|
7
|
+
type: feature
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-10-19
|
|
10
|
+
owners: [jcardinal]
|
|
11
|
+
files:
|
|
12
|
+
- _underscore/Model/Client/ServiceRequests/Ticket.php
|
|
13
|
+
- _underscore/Model/Client/ServiceRequests/ServiceRequest.php
|
|
14
|
+
- _underscore/Model/Client/ServiceRequest.php
|
|
15
|
+
- _underscore/Component/TicketMerge/TicketMerge.php
|
|
16
|
+
- dbchanges2/Client/2026-10-18m - TRUE-82911 ServiceRequestLinks.sql
|
|
17
|
+
- dbchanges2/Core/2026-10-18u - TRUE-82911 ServiceRequestLinksCore.sql
|
|
18
|
+
related:
|
|
19
|
+
- ./record-hard-delete.md
|
|
20
|
+
---
|
|
21
|
+
Many-to-many links from a service request to tickets and to other service requests; open before linking SRs, reading `_linkCount`, or touching the old `ServiceRequests.ticketId` / `Tickets.serviceRequestId` FKs.
|
|
22
|
+
|
|
23
|
+
## Summary
|
|
24
|
+
|
|
25
|
+
The single FKs `ServiceRequests.ticketId` and `Tickets.serviceRequestId` hold one link each, so many links per kind
|
|
26
|
+
moved to two bridge tables (TRUE-82911; toga25-desk ADR 0165 amends 0119/0127). Core Records 418
|
|
27
|
+
`service-request-tickets`, 419 `service-request-service-requests`.
|
|
28
|
+
|
|
29
|
+
## How it works
|
|
30
|
+
|
|
31
|
+
- **`ServiceRequests_Tickets`**, **`ServiceRequests_ServiceRequests`** — link rows are added or removed, never edited
|
|
32
|
+
(PUT/PATCH → 400).
|
|
33
|
+
- **SR ↔ SR stored once, lower id first.** Query both columns when reading a request's links.
|
|
34
|
+
- **PRE POST checks:** caller needs READ on both records; refuses self-links, duplicates, and pairs already tied by
|
|
35
|
+
the old FKs (400 with a readable message).
|
|
36
|
+
- **Old FK links still count as links.** `ServiceRequest::_linkCount` (non-stored) counts both bridges plus
|
|
37
|
+
`Cases_ServiceRequests`; unlinking an FK-tied pair clears the FK instead of deleting a bridge row.
|
|
38
|
+
- **Delete:** the service request's `relatedRows()` clears its link rows.
|
|
39
|
+
- **Ticket merge:** `_Component_TicketMerge` moves `ServiceRequests_Tickets` rows to the surviving ticket and drops
|
|
40
|
+
duplicates.
|
|
41
|
+
|
|
42
|
+
## Change history
|
|
43
|
+
- 2026-10-19 — Created: SR ↔ ticket and SR ↔ SR bridges replace one-link FKs (TRUE-82911). (jcardinal)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Table view presets (saved views — TableViewPresets.config whitelist)
|
|
3
|
+
framework: "2.0"
|
|
4
|
+
repo: _underscore
|
|
5
|
+
project: _Underscore
|
|
6
|
+
client: shared
|
|
7
|
+
type: feature
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-10-19
|
|
10
|
+
owners: [jcardinal]
|
|
11
|
+
files:
|
|
12
|
+
- _underscore/Model/Client/TableViewPreset.php
|
|
13
|
+
related:
|
|
14
|
+
- ./tableview-joins.md
|
|
15
|
+
- ../../api2/features/api-payload-interceptors.md
|
|
16
|
+
---
|
|
17
|
+
A user's saved table view stored as one validated JSON `config`; open before adding anything new to what a saved view remembers.
|
|
18
|
+
|
|
19
|
+
## Summary
|
|
20
|
+
|
|
21
|
+
`/v2/table-view-presets` (Core Records 352, generic dispatcher, no controller). One row = one user's named snapshot
|
|
22
|
+
of a table: columns, up to 3 sorts, filters, group, search. Per-user (`userId` NOT NULL, own rows only) — a
|
|
23
|
+
"default view" from a design cannot be seeded for everyone.
|
|
24
|
+
|
|
25
|
+
## How it works
|
|
26
|
+
|
|
27
|
+
- **PRE POST / PRE PUT** stamp ownership and run `validateConfig()`. POST needs `config`; a PUT without `config`
|
|
28
|
+
(rename, set default) keeps the stored one.
|
|
29
|
+
- **`validateConfig()` rebuilds the JSON from a whitelist:** `columns`, `sorts`, `filters`, `group`, `search`.
|
|
30
|
+
Field tokens must match `FIELD_TOKEN_PATTERN`; filter operators only `eq`, `in`, `ge`, `lt`, `contains`; values
|
|
31
|
+
scalar only. Bad input → 400.
|
|
32
|
+
- **`search`** (added 2026-10-19): optional string, trimmed, max `MAX_SEARCH_LENGTH` 255, blank → `null`; not a
|
|
33
|
+
string or too long → 400. Old presets without it stay valid. Stored only, never used in SQL here.
|
|
34
|
+
|
|
35
|
+
## Gotchas
|
|
36
|
+
|
|
37
|
+
- **A new config key is silently dropped on save** unless you add it to the whitelist in `validateConfig()` with
|
|
38
|
+
its own validator. No error — the key just never comes back.
|
|
39
|
+
|
|
40
|
+
## Change history
|
|
41
|
+
- 2026-10-19 — Created; `search` added to the config whitelist (TRUE-82911). (jcardinal)
|
|
@@ -6,7 +6,7 @@ project: API
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-10-
|
|
9
|
+
updated: 2026-10-19
|
|
10
10
|
owners: [jcardinal]
|
|
11
11
|
files:
|
|
12
12
|
- api2/Component/Api/CrossClient/CrossClient.php
|
|
@@ -132,6 +132,11 @@ Page 1 of 25 still fetches exactly 25; page 254 fetches 500 per pass — ~13 rou
|
|
|
132
132
|
`client=` on another tenant's token makes `resolveScope()` fan out to THAT tenant's `Users_Clients`
|
|
133
133
|
(cross-tenant read). Seeded uuids also repeat across `Client_*` DBs, so multi-client UI rows must be
|
|
134
134
|
keyed by client uuid + record uuid. Full rule: toga25-desk ADR 0154, `GOTCHAS.md`.
|
|
135
|
+
- **⚠ One ungranted field fails the WHOLE cross-client read with 403** — "Cross-client sub-request failed … You do
|
|
136
|
+
not have the necessary permissions to read the specified fields". This includes `_`-prefixed calc fields, which a
|
|
137
|
+
single-client read lets through. Example: Items `_label` (RecordFields 2599) had no `AclFieldPermissions` grant
|
|
138
|
+
anywhere until 2026-10-19 (`Client/2026-10-19e`, `Core/2026-10-19g`; granted like `_imageUrl` 1276: Core Super
|
|
139
|
+
User + client capability Base). Before a consumer names a field, check the grant exists for the caller's roles.
|
|
135
140
|
- **`curl_multi` busy-spin guard** — both multi loops `usleep(100)` when `curl_multi_select() === -1`.
|
|
136
141
|
- **Known limitation — deep page-number paging is inherently O(page).** Serving page 4430 means materializing all 110,747 preceding rows into the cache. Adaptive chunking makes that cheaper, not cheap: cost still grows with depth, because a page **number** cannot be resolved without knowing everything before it. The durable answer is **exposing keyset cursors to the caller** so cost is independent of depth — the mechanism already exists (V2 supports `seekValues` + `seekUuid` correctly). Raised with the developer 2026-07-28 and **deliberately left unbuilt / not yet scoped**: a known limitation and candidate direction, not pending work.
|
|
137
142
|
|
|
@@ -145,6 +150,7 @@ Page 1 of 25 still fetches exactly 25; page 254 fetches 500 per pass — ~13 rou
|
|
|
145
150
|
- [_Model magic-field access](../../_underscore/features/model-magic-field-access.md)
|
|
146
151
|
|
|
147
152
|
## Change history
|
|
153
|
+
- 2026-10-19 — One ungranted field (calc fields too) fails the whole cross-client read with 403; Items `_label` granted (TRUE-82911). (jcardinal)
|
|
148
154
|
- 2026-10-17 — Home vs linked user rows; `Users_Clients` is the reach list, linked rows drift (TRUE-82872). (jcardinal)
|
|
149
155
|
- 2026-10-17 — Fetch scope is `client=` OR own token, never both; key multi-client rows by client + record uuid (TRUE-82903). (jcardinal)
|
|
150
156
|
- 2026-10-17 — Internal-request writes must add their own `cacheInvalidations` (TRUE-82889). (jcardinal)
|
|
@@ -6,7 +6,7 @@ project: API
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-10-
|
|
9
|
+
updated: 2026-10-19
|
|
10
10
|
owners: [tcox, bala, apeterson, jcardinal, rgirish]
|
|
11
11
|
files:
|
|
12
12
|
- api2/Component/Api/V2/V2.php
|
|
@@ -389,7 +389,9 @@ where=(field:op:value,LOGIC,field:op:value,(nested,OR,nested))
|
|
|
389
389
|
`field:ne:null` → `IS NOT NULL`.
|
|
390
390
|
- **A dotted FK path (`case.uuid`) in `where` fails `EV-8` on a list GET.** Filter by a parent FK
|
|
391
391
|
through a join alias: `ojoin=Cases:Cases.id=Tickets.caseId&where=(Cases.uuid:eq:<uuid>)` (or a
|
|
392
|
-
`TableViewJoins` row that gives the alias).
|
|
392
|
+
`TableViewJoins` row that gives the alias). **Self-join (FK to the same table, e.g.
|
|
393
|
+
`parentLocation.uuid`) needs an alias:** `ojoin=Locations@p:p.id=Locations.parentLocationId&where=(p.uuid:eq:<uuid>)`.
|
|
394
|
+
A path through an **inherent child**
|
|
393
395
|
(`ticketUsers.user.uuid`) does work — but only when the **first** segment is an inherent child
|
|
394
396
|
of the route (`buildChildPathWhereSql`). A path that starts with a forward FK hop fails
|
|
395
397
|
(`service-requests` → `ticket.ticketUsers.user.uuid`). No-api2-change fix: a TableView that
|
|
@@ -568,6 +570,10 @@ ACL gate for calculated fields lives at **:7216** in `getFullModelData()` — wh
|
|
|
568
570
|
**Corollary for the `fields=`-forces-`EZ-2` diagnostic above:** re-requesting with an explicit
|
|
569
571
|
`fields=` list to smoke out a denied field **only works on plain columns**. It will never produce an
|
|
570
572
|
`EZ-2` for a `_`-prefixed field, so a silent `0` is not evidence that the grant exists.
|
|
573
|
+
|
|
574
|
+
**⚠ The bypass does NOT hold on a cross-client (`client=`) read** — an ungranted calc field there fails the whole
|
|
575
|
+
read with 403. Grant every `_` field a consumer names. See
|
|
576
|
+
[cross-client gotchas](cross-client-data-retrieval.md#gotchas).
|
|
571
577
|
- **`EZ-1` vs `EZ-2` for a consumer:** `EZ-1` = record-level block (`data.<route>` is `null`) —
|
|
572
578
|
hard blocked, nothing usable. `EZ-2` = field-level — on a **LIST** it is
|
|
573
579
|
*degraded-but-usable*; on a **by-uuid READ** it is **fatal**.
|
|
@@ -650,6 +656,7 @@ If you need the behaviour, loop uuids client-side. Point 3 is the durable, non-o
|
|
|
650
656
|
[V2 request logging](request-logging.md).
|
|
651
657
|
|
|
652
658
|
## Change history
|
|
659
|
+
- 2026-10-19 — Self-join `where` needs an `ojoin` alias (`Locations@p`); `_` field ACL bypass does not apply cross-client (TRUE-82911). (jcardinal)
|
|
653
660
|
- 2026-10-18 — Grouped queries: stored root group key now selected + ACL-gated; known gaps (joined key, total count, `ORDER BY uuid` under ONLY_FULL_GROUP_BY) (TRUE-82876). (jcardinal)
|
|
654
661
|
- 2026-10-17 — Child-path `where` must start at an inherent child; FK-first path → TableView join alias (TRUE-82872). (jcardinal)
|
|
655
662
|
- 2026-10-17 — Multi-sort comma list + `uuid` tie-breaker for stable paging; sort on calc works; refreshed where-path line refs. (jcardinal)
|
package/knowledge/INDEX.md
CHANGED
|
@@ -12,7 +12,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
|
|
|
12
12
|
- **togaview** (TOGa View) — 8 doc(s) → [1.0/apps/togaview/INDEX.md](1.0/apps/togaview/INDEX.md)
|
|
13
13
|
- **webhook** (Webhook) — 1 doc(s) → [1.0/apps/webhook/INDEX.md](1.0/apps/webhook/INDEX.md)
|
|
14
14
|
- **walmarttechservices** (Walmart Tech Services) — 1 doc(s) → [1.0/apps/walmarttechservices/INDEX.md](1.0/apps/walmarttechservices/INDEX.md)
|
|
15
|
-
- **test** (Test) —
|
|
15
|
+
- **test** (Test) — 18 doc(s) → [1.0/apps/test/INDEX.md](1.0/apps/test/INDEX.md)
|
|
16
16
|
- **toga** (TOGa) — 4 doc(s) → [1.0/apps/toga/INDEX.md](1.0/apps/toga/INDEX.md)
|
|
17
17
|
- **store** (Store) — 4 doc(s) → [1.0/apps/store/INDEX.md](1.0/apps/store/INDEX.md)
|
|
18
18
|
- **tools** (Tools) — 25 doc(s) → [1.0/apps/tools/INDEX.md](1.0/apps/tools/INDEX.md)
|
|
@@ -21,7 +21,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
|
|
|
21
21
|
|
|
22
22
|
## 2.0 framework
|
|
23
23
|
|
|
24
|
-
- **_underscore** (_Underscore) _(framework core)_ —
|
|
24
|
+
- **_underscore** (_Underscore) _(framework core)_ — 110 doc(s) → [2.0/apps/_underscore/INDEX.md](2.0/apps/_underscore/INDEX.md)
|
|
25
25
|
- **worker2** (Worker) — 90 doc(s) → [2.0/apps/worker2/INDEX.md](2.0/apps/worker2/INDEX.md)
|
|
26
26
|
- **api2** (API) — 27 doc(s) → [2.0/apps/api2/INDEX.md](2.0/apps/api2/INDEX.md)
|
|
27
27
|
- **dbchanges2** (Database Changes) _(framework core)_ — 22 doc(s) → [2.0/apps/dbchanges2/INDEX.md](2.0/apps/dbchanges2/INDEX.md)
|
package/package.json
CHANGED