Skip to content

Commit 92ce3af

Browse files
fix(plugin-approvals,plugin-audit,plugin-sharing): list views drop the target object's API name column beside a record pointer (#24600)
Fixes #24501 Clause-②: no ## Parked: draft until the console pin carries the type-half fetch This PR stays **draft** until objectstack's `.objectui-sha` on `origin/main` has objectui `fe11eb12e578fe38cff8ba454de6507bd99daa2a` as an ancestor. That commit is objectstack-ai/objectui#13042, which answers objectstack-ai/objectui#13036. Landing this PR earlier turns the Record column of every list below into raw record ids, because the console at the current pin fetches only a list's shown columns, and the pointer cell resolves its record from the row's type half. - **The pin today** is `4016370af3c9`, committed 2026-10-19T03:42Z. The fix was committed at 11:29Z. In the objectui clone, `git merge-base --is-ancestor fe11eb1 4016370` answers exit 1. The clone is shallow, so a control leg ran on the same clone: `4016370af3c9~30` (`b5153f44ea`) answers exit 0. - **Expected-red list: empty.** No PR or merge-queue check draws these lists through the console, so nothing here turns red while the PR is parked. The parking is about what users see. - **Unlock:** a pin bump past `fe11eb12e5` lands on `main`. This PR does not move the pin. After that: sync with `main`, re-check, ready, queue. ## What changes `object_name` (a `Field.text` labelled "Object" that holds the target object's API name, such as `showcase_announcement`) leaves the `columns` of every list view where it sat beside its `record_id` pointer id half (`referenceVia: 'object_name'`): | Object | Views | |---|---| | `sys_approval_request` | `all_requests`, `my_pending`, `submitted_by_me`, `completed` | | `sys_approval_action` | `recent`, `all_actions` (`by_actor` never listed it) | | `sys_audit_log` | `recent`, `writes_only`, `record_views`, `all_events` | | `sys_record_share` | `all_shares`, `granted_to_me`, `granted_by_me`, `by_object`, `manual_grants`, `rule_grants` | | `sys_share_link` | `active_links`, `by_me`, `revoked`, `all_links` | - **Left as is:** `sys_audit_log.config_changes` lists `object_name` without `record_id`. Its rows (`config_change` and `import`) carry no `record_id`, so no pointer names their target. That view does not follow this pattern and is unchanged. - `object_name` stays a declared field on all five objects. The pointer pair, its indexes, `highlightFields`, `titleFormat` and every query on the pair are untouched. Only list `columns` move. - The Record column keeps drawing the target record (its object's icon and the record's name), once the console fetches the type half for the cell. ## Readings behind the route (seat answer `6264371362`, route A) - **A1, the positions,** re-read on `origin/main` `de4352460`. Every view in the table lists `object_name` immediately beside `record_id`, and each object's `record_id` declares `referenceVia: 'object_name'` (request `:263`, action `:154`, audit log `:321`, record share `:172`, share link `:168`, before this diff). `config_changes` is the one view that lists the type half without the id half. - **A2, the console half,** read from objectui `fe11eb12e5` (`git show`, read-only). Both projection builders now request the sibling. `ListView` `selectFields` adds `referenceVia` of every FLS-surviving column through `addSpeculative`, which covers ListView's own fetch. `ObjectGrid` `getSelectFields` adds a `referenceViaFields` harvest to `extraFields`, which covers the fetch a grouped grid owns (`gridOwnsGroupedFetch`) and a standalone `object-grid`. The fix is on objectui `main` (`8aa8e3e1e5`, ancestor check exit 0). - **A3, the approvals pin:** case (f) of `approval-list-display-labels.integration.test.ts` asserted that `recent` / `all_actions` contain `object_name`, `record_id` and `acted_as_label`. It now asserts `record_id` and `acted_as_label`, and that `object_name` is absent. ## Pins Each package now enumerates its own objects' list views. The approvals pin uses the objects `ApprovalsServicePlugin` registers. The audit and sharing pins use `objects/index.ts`. Each pin asserts two things: 1. No list view shows a `referenceVia` sibling beside its id half. 2. The family's views still show the id half, so the Record column names the target. The pins live in `sys-approval-request-pointer-pair.test.ts`, `sys-audit-log-pointer-pair.test.ts` and `sharing-pointer-pairs.test.ts`. **Ablation** (one `object_name` put back per package, at commit `c62273124`, through `scripts/ablation-replace.mjs` in wrap mode). The mutation landed each time (anchor x1 to x0, blob changed). Exactly one test went red each time, `no list view shows a referenceVia sibling beside its id half` (`expected [ Array(1) ] to deeply equal []`; approvals names `sys_approval_request.all_requests: object_name`). The file was restored each time with blob equal to `HEAD` and an empty `git diff HEAD`: | Package | Mutated view | Vitest exit | |---|---|---| | plugin-sharing | `sys_record_share.all_shares` | 1 | | plugin-audit | `sys_audit_log.record_views` | 1 | | plugin-approvals | `sys_approval_request.all_requests` | 1 | The tests import the objects by relative source path, so the ablation needed no rebuild. ## Verification, at `c62273124` All of this ran under `scripts/pm/os-verify-lock.sh`: - **Build:** the dependency closure of the three packages, then the packages themselves. Both exited 0. - **Tests:** `@objectstack/plugin-approvals` had 81 files and 1114 tests pass; `@objectstack/plugin-audit` 56 files and 899 tests; `@objectstack/plugin-sharing` 49 files and 1163 tests. Every run exited 0. - **Typecheck:** `pnpm --filter` with the three packages, `run typecheck`, exited 0. `check:test-typecheck` was OK for all three, and the edited test files gained no ledger entries. - **Derived gates:** `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` gave 67 commands, and all 67 ran with exit 0. - Two of them first exited 3 (`PREREQUISITE NOT MET`): `check:i18n` and `check:dual-build-cjs-loads`. After a full workspace build, both re-ran with exit 0. - `--ran` reports: "67 derived, 67 run, 0 NOT-MEASURED, 0 UNRUN". - **Declared to CI:** `test:repo`, the whole-tree families, the type-check lanes and Build Core. - **Not measured: a browser reading of the lists.** The bundled console at the pin predates the fix. A reading against objectui `main` needs an objectui worktree build, and it belongs to the unlock, when the bundled console carries the fix. ## Acceptance notes - **Rows without a `record_id` lose their target hint.** `sys_audit_log`'s `recent` and `all_events` also list `config_change` and `import` rows. Those carry `object_name` (`sys_setting`, `sys_platform_setting`, `sys_user`) and no `record_id`. They now show an empty Record cell, and the action column says what they are. The `config_changes` view still shows their object. - **`sys_record_share.by_object` still groups and sorts on `object_name`.** The console fetches the grouping field, so the group header still reads the API name. That is a grouping, not a column, and it is outside this card's surface. It is reported to the seat with the next note. - **Not in this card's surface, reported to the seat:** these record-page surfaces still name the target by its API name: - `sys_audit_log`, `sys_record_share` and `sys_share_link` list `object_name` in `highlightFields`. - `sys_record_share` and `sys_share_link` have no `nameField`, and their `titleFormat` starts with `{object_name}/{record_id}`. --- _Generated by [Claude Code](https://claude.ai/code/session_01LR1cD9JqgkeqY7k9rrZH8s)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent eadea57 commit 92ce3af

10 files changed

Lines changed: 231 additions & 22 deletions
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
'@objectstack/plugin-approvals': patch
3+
'@objectstack/plugin-audit': patch
4+
'@objectstack/plugin-sharing': patch
5+
---
6+
7+
fix(plugin-approvals, plugin-audit, plugin-sharing): list views no longer show the target object's API name as an Object column
8+
9+
Clause-②: no
10+
11+
- **The Object column leaves these lists.** These list views showed `object_name`, the target object's API name (such as `showcase_announcement`), as plain text beside the `record_id` record pointer. They no longer list it:
12+
- `sys_approval_request`: `all_requests`, `my_pending`, `submitted_by_me` and `completed`;
13+
- `sys_approval_action`: `recent` and `all_actions`;
14+
- `sys_audit_log`: `recent`, `writes_only`, `record_views` and `all_events`;
15+
- `sys_record_share`: all six views;
16+
- `sys_share_link`: all four views.
17+
- **The Record column names the target record.** `record_id` is the id half of the `record_id` / `object_name` pointer pair. The console draws it as the target record, with its object's icon and the record's name, and fetches `object_name` for that cell without a column. This relies on a console that fetches a pointer's type half for its cell, as the console bundled with this release does; an older console draws the raw record id in that column.
18+
- **Unchanged:** `object_name` stays a declared field on all five objects, and the pointer pair, its indexes and every query on it are untouched. `sys_audit_log`'s `config_changes` view keeps its Object column, because its rows carry no `record_id`.
19+
20+
A patch: entries removed from list view `columns` on shipped platform objects. No export, type, accepted value, served key or stored column changes.

‎packages/plugins/plugin-approvals/src/approval-list-display-labels.integration.test.ts‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,10 @@ describe('#23889 — the approval lists read engine-written display columns', ()
288288
for (const col of view.columns) expect(act.fields[col], `${name}.${col}`).toBeDefined();
289289
}
290290
for (const name of ['recent', 'all_actions']) {
291-
expect(act.listViews[name].columns, name).toEqual(expect.arrayContaining(['object_name', 'record_id', 'acted_as_label']));
291+
// The pointer shows as its id half; the type half is fetched for that
292+
// cell, never shown as a column (`sys-approval-request-pointer-pair.test.ts`).
293+
expect(act.listViews[name].columns, name).toEqual(expect.arrayContaining(['record_id', 'acted_as_label']));
294+
expect(act.listViews[name].columns, name).not.toContain('object_name');
292295
expect(act.listViews[name].columns, name).not.toContain('acted_as');
293296
}
294297
expect(act.fields.record_id.referenceVia).toBe('object_name');

‎packages/plugins/plugin-approvals/src/sys-approval-action.object.ts‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,17 @@ export const SysApprovalAction = ObjectSchema.create({
4747
// (`object_name` + `record_id`) are written by `ApprovalService` with the row,
4848
// copied from the request it belongs to (`actionRow`). The row is
4949
// append-only, so each is the engine's fact at the moment of the action; a
50-
// list shows them as stored and never re-derives them.
50+
// list shows them as stored and never re-derives them. The pointer shows as
51+
// its id half, `record_id`, which the console draws as the target record and
52+
// resolves through `object_name` without a column (objectui#13036); no list
53+
// view shows the type half (`sys-approval-request-pointer-pair.test.ts`).
5154
listViews: {
5255
recent: {
5356
type: 'grid',
5457
name: 'recent',
5558
label: 'Recent',
5659
data: { provider: 'object', object: 'sys_approval_action' },
57-
columns: ['created_at', 'object_name', 'record_id', 'request_id', 'step_label', 'action', 'actor_id', 'acted_as_label', 'via_override', 'comment'],
60+
columns: ['created_at', 'record_id', 'request_id', 'step_label', 'action', 'actor_id', 'acted_as_label', 'via_override', 'comment'],
5861
sort: [{ field: 'created_at', order: 'desc' }],
5962
pagination: { pageSize: 50 },
6063
emptyState: { title: 'No approval actions yet', message: 'Actions are logged automatically when approvals progress.' },
@@ -74,7 +77,7 @@ export const SysApprovalAction = ObjectSchema.create({
7477
name: 'all_actions',
7578
label: 'All',
7679
data: { provider: 'object', object: 'sys_approval_action' },
77-
columns: ['created_at', 'object_name', 'record_id', 'request_id', 'step_label', 'action', 'actor_id', 'acted_as_label', 'via_override', 'comment'],
80+
columns: ['created_at', 'record_id', 'request_id', 'step_label', 'action', 'actor_id', 'acted_as_label', 'via_override', 'comment'],
7881
sort: [{ field: 'created_at', order: 'desc' }],
7982
pagination: { pageSize: 100 },
8083
},

‎packages/plugins/plugin-approvals/src/sys-approval-request-pointer-pair.test.ts‎

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { describe, it, expect } from 'vitest';
44
import { ObjectSchema } from '@objectstack/spec/data';
5+
import { ApprovalsServicePlugin } from './approvals-plugin.js';
56
import { SysApprovalRequest } from './sys-approval-request.object.js';
67

78
/**
@@ -77,3 +78,64 @@ describe('sys_approval_request — record_id tombstone predicate', () => {
7778
expect(parsed.success, parsed.success ? '' : JSON.stringify(parsed.error.issues)).toBe(true);
7879
});
7980
});
81+
82+
/**
83+
* [#24501] A list names a pointer's target with the id half alone. The console
84+
* draws a `referenceVia` column as the target record (its object's icon and
85+
* name) and fetches the type half for that cell without a column
86+
* (objectui#13036); a type-half column draws the stored API name as text.
87+
* Enumerated over every object the plugin registers, so a view added later is
88+
* judged without anyone listing it here.
89+
*/
90+
describe('approvals list views — a pointer shows as its id half, never its type half (#24501)', () => {
91+
type PointerObject = {
92+
name: string;
93+
fields: Record<string, { referenceVia?: unknown } | undefined>;
94+
listViews?: Record<string, { columns?: ReadonlyArray<string | { field: string }> }>;
95+
};
96+
97+
async function registeredObjects(): Promise<PointerObject[]> {
98+
const registered: Array<{ objects: PointerObject[] }> = [];
99+
const ctx: any = {
100+
getService: (name: string) =>
101+
name === 'manifest' ? { register: (m: { objects: PointerObject[] }) => registered.push(m) } : undefined,
102+
logger: { info: () => {}, warn: () => {} },
103+
};
104+
await new ApprovalsServicePlugin({ disableService: true }).init(ctx);
105+
expect(registered).toHaveLength(1);
106+
return registered[0].objects;
107+
}
108+
109+
/** `object.view: column` for each shown id half, and for each type half shown beside one. */
110+
function pointerColumns(objects: readonly PointerObject[]): { idHalves: string[]; typeHalves: string[] } {
111+
const idHalves: string[] = [];
112+
const typeHalves: string[] = [];
113+
for (const object of objects) {
114+
for (const [view, def] of Object.entries(object.listViews ?? {})) {
115+
const shown = new Set((def.columns ?? []).map((c) => (typeof c === 'string' ? c : c.field)));
116+
for (const column of shown) {
117+
const via = object.fields[column]?.referenceVia;
118+
if (typeof via !== 'string') continue;
119+
idHalves.push(`${object.name}.${view}: ${column}`);
120+
if (shown.has(via)) typeHalves.push(`${object.name}.${view}: ${via}`);
121+
}
122+
}
123+
}
124+
return { idHalves, typeHalves };
125+
}
126+
127+
it('no list view shows a referenceVia sibling beside its id half', async () => {
128+
expect(pointerColumns(await registeredObjects()).typeHalves).toEqual([]);
129+
});
130+
131+
it('the request and action lists still show the id half, so the Record column names the target', async () => {
132+
expect(pointerColumns(await registeredObjects()).idHalves).toEqual(expect.arrayContaining([
133+
'sys_approval_request.all_requests: record_id',
134+
'sys_approval_request.my_pending: record_id',
135+
'sys_approval_request.submitted_by_me: record_id',
136+
'sys_approval_request.completed: record_id',
137+
'sys_approval_action.recent: record_id',
138+
'sys_approval_action.all_actions: record_id',
139+
]));
140+
});
141+
});

‎packages/plugins/plugin-approvals/src/sys-approval-request.object.ts‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,20 @@ export const SysApprovalRequest = ObjectSchema.create({
9191
// reads them as stored and never re-derives a label from flow metadata or
9292
// resolves an approver address itself; `process_name`, `current_step` and
9393
// `pending_approvers` keep the machine values every query and decision reads.
94+
//
95+
// The target is the `record_id` column alone. It is the pointer's id half,
96+
// so the console draws the target record (its object's icon and name) and
97+
// fetches the type half `object_name` for that cell without a column
98+
// (objectui#13036). An `object_name` column drew the stored API name as
99+
// text; no list view shows a pointer's type half
100+
// (`sys-approval-request-pointer-pair.test.ts`).
94101
listViews: {
95102
all_requests: {
96103
type: 'grid',
97104
name: 'all_requests',
98105
label: 'All',
99106
data: { provider: 'object', object: 'sys_approval_request' },
100-
columns: ['process_label', 'object_name', 'record_id', 'status', 'current_step_label', 'pending_approver_labels', 'submitter_id', 'updated_at'],
107+
columns: ['process_label', 'record_id', 'status', 'current_step_label', 'pending_approver_labels', 'submitter_id', 'updated_at'],
101108
sort: [{ field: 'updated_at', order: 'desc' }],
102109
pagination: { pageSize: 50 },
103110
},
@@ -106,7 +113,7 @@ export const SysApprovalRequest = ObjectSchema.create({
106113
name: 'my_pending',
107114
label: 'My Pending',
108115
data: { provider: 'object', object: 'sys_approval_request' },
109-
columns: ['process_label', 'object_name', 'record_id', 'current_step_label', 'pending_approver_labels', 'submitter_id', 'updated_at'],
116+
columns: ['process_label', 'record_id', 'current_step_label', 'pending_approver_labels', 'submitter_id', 'updated_at'],
110117
filter: [
111118
{ field: 'status', operator: 'equals', value: 'pending' },
112119
{ field: 'pending_approvers', operator: 'contains', value: '{current_user_id}' },
@@ -120,7 +127,7 @@ export const SysApprovalRequest = ObjectSchema.create({
120127
name: 'submitted_by_me',
121128
label: 'I Submitted',
122129
data: { provider: 'object', object: 'sys_approval_request' },
123-
columns: ['process_label', 'object_name', 'record_id', 'status', 'current_step_label', 'updated_at'],
130+
columns: ['process_label', 'record_id', 'status', 'current_step_label', 'updated_at'],
124131
filter: [{ field: 'submitter_id', operator: 'equals', value: '{current_user_id}' }],
125132
sort: [{ field: 'updated_at', order: 'desc' }],
126133
pagination: { pageSize: 25 },
@@ -130,7 +137,7 @@ export const SysApprovalRequest = ObjectSchema.create({
130137
name: 'completed',
131138
label: 'Completed',
132139
data: { provider: 'object', object: 'sys_approval_request' },
133-
columns: ['process_label', 'object_name', 'record_id', 'status', 'submitter_id', 'completed_at'],
140+
columns: ['process_label', 'record_id', 'status', 'submitter_id', 'completed_at'],
134141
// Every terminal state, `cancelled` included (#13568) — a platform-voided
135142
// request is kept as audit evidence, and a terminal state absent from the
136143
// only curated terminal view is evidence nobody can find.

‎packages/plugins/plugin-audit/src/objects/sys-audit-log.object.ts‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,20 @@ export const SysAuditLog = ObjectSchema.create({
4444
titleFormat: '{action} · {object_name}',
4545
highlightFields: ['created_at', 'action', 'object_name', 'record_id', 'user_id'],
4646

47+
// A list names the target with the pointer's id half, `record_id`: the
48+
// console draws it as the target record and fetches the type half
49+
// `object_name` for that cell without a column (objectui#13036). A list
50+
// view never shows the type half beside it, which would draw the stored API
51+
// name as text (`sys-audit-log-pointer-pair.test.ts`). `config_changes`
52+
// keeps `object_name`: its rows carry no `record_id`, so no pointer names
53+
// their target.
4754
listViews: {
4855
recent: {
4956
type: 'grid',
5057
name: 'recent',
5158
label: 'Recent',
5259
data: { provider: 'object', object: 'sys_audit_log' },
53-
columns: ['created_at', 'action', 'object_name', 'record_id', 'user_id'],
60+
columns: ['created_at', 'action', 'record_id', 'user_id'],
5461
sort: [{ field: 'created_at', order: 'desc' }],
5562
pagination: { pageSize: 50 },
5663
emptyState: { title: 'No audit events', message: 'Activity will appear here as users interact with the platform.' },
@@ -60,7 +67,7 @@ export const SysAuditLog = ObjectSchema.create({
6067
name: 'writes_only',
6168
label: 'Writes',
6269
data: { provider: 'object', object: 'sys_audit_log' },
63-
columns: ['created_at', 'action', 'object_name', 'record_id', 'user_id'],
70+
columns: ['created_at', 'action', 'record_id', 'user_id'],
6471
// `restore` removed (#8315): the value is retired from the enum, so the
6572
// filter would have matched nothing for the rest of time. The three that
6673
// remain are exactly what `actionFor()` in `audit-writers.ts` can emit.
@@ -105,7 +112,7 @@ export const SysAuditLog = ObjectSchema.create({
105112
name: 'record_views',
106113
label: 'Record Views',
107114
data: { provider: 'object', object: 'sys_audit_log' },
108-
columns: ['created_at', 'user_id', 'object_name', 'record_id', 'actor'],
115+
columns: ['created_at', 'user_id', 'record_id', 'actor'],
109116
filter: [{ field: 'action', operator: 'in', value: ['read'] }],
110117
sort: [{ field: 'created_at', order: 'desc' }],
111118
pagination: { pageSize: 50 },
@@ -137,7 +144,7 @@ export const SysAuditLog = ObjectSchema.create({
137144
name: 'all_events',
138145
label: 'All',
139146
data: { provider: 'object', object: 'sys_audit_log' },
140-
columns: ['created_at', 'action', 'object_name', 'record_id', 'user_id'],
147+
columns: ['created_at', 'action', 'record_id', 'user_id'],
141148
sort: [{ field: 'created_at', order: 'desc' }],
142149
pagination: { pageSize: 100 },
143150
},

‎packages/plugins/plugin-audit/src/sys-audit-log-pointer-pair.test.ts‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { describe, it, expect } from 'vitest';
44
import { SysAuditLog } from './objects/sys-audit-log.object.js';
5+
import * as AuditObjects from './objects/index.js';
56

67
/**
78
* `sys_audit_log` declares the ActivityPointer pair — #11386 (ADR-0052 §5,
@@ -52,3 +53,52 @@ describe('sys_audit_log — declared pointer pair (#11386)', () => {
5253
expect(fields.object_name.required ?? false).toBe(false);
5354
});
5455
});
56+
57+
/**
58+
* [#24501] A list names a pointer's target with the id half alone. The console
59+
* draws a `referenceVia` column as the target record (its object's icon and
60+
* name) and fetches the type half for that cell without a column
61+
* (objectui#13036); a type-half column draws the stored API name as text.
62+
* Enumerated over every object this package ships (`objects/index.ts`), so a
63+
* view added later is judged without anyone listing it here.
64+
*/
65+
describe('audit list views — a pointer shows as its id half, never its type half (#24501)', () => {
66+
type PointerObject = {
67+
name: string;
68+
fields: Record<string, { referenceVia?: unknown } | undefined>;
69+
listViews?: Record<string, { columns?: ReadonlyArray<string | { field: string }> }>;
70+
};
71+
72+
/** `object.view: column` for each shown id half, and for each type half shown beside one. */
73+
function pointerColumns(objects: readonly PointerObject[]): { idHalves: string[]; typeHalves: string[] } {
74+
const idHalves: string[] = [];
75+
const typeHalves: string[] = [];
76+
for (const object of objects) {
77+
for (const [view, def] of Object.entries(object.listViews ?? {})) {
78+
const shown = new Set((def.columns ?? []).map((c) => (typeof c === 'string' ? c : c.field)));
79+
for (const column of shown) {
80+
const via = object.fields[column]?.referenceVia;
81+
if (typeof via !== 'string') continue;
82+
idHalves.push(`${object.name}.${view}: ${column}`);
83+
if (shown.has(via)) typeHalves.push(`${object.name}.${view}: ${via}`);
84+
}
85+
}
86+
}
87+
return { idHalves, typeHalves };
88+
}
89+
90+
const objects = Object.values(AuditObjects) as unknown as PointerObject[];
91+
92+
it('no list view shows a referenceVia sibling beside its id half', () => {
93+
expect(pointerColumns(objects).typeHalves).toEqual([]);
94+
});
95+
96+
it('the ledger lists still show the id half, so the Record column names the target', () => {
97+
expect(pointerColumns(objects).idHalves).toEqual(expect.arrayContaining([
98+
'sys_audit_log.recent: record_id',
99+
'sys_audit_log.writes_only: record_id',
100+
'sys_audit_log.record_views: record_id',
101+
'sys_audit_log.all_events: record_id',
102+
]));
103+
});
104+
});

0 commit comments

Comments
 (0)