Skip to content

Commit 5c58fab

Browse files
committed
fix(objectql): the update path's pre-strip validation is spelled validateRecord again
ADR-0020 anchors packages/objectql/src/engine.ts#validateRecord and quotes the update path's call, validateRecord(schema, hookContext.input.data, 'update'), as the one that sees only the PATCH payload. Spelling that call as validateRecordInScope(..., 'skip', ...) left the anchor unresolved (check:adr-symbol-anchors). The public validateRecord IS that scope, so the two pre-strip calls use it again: no behaviour change, the anchor resolves on the call it names, and the ADR text stays true as written. Claude-Session: https://claude.ai/code/session_017ErfyP2Rx7XWHJA27QjyUi Co-authored-by: Claude <noreply@anthropic.com>
1 parent b73f58e commit 5c58fab

1 file changed

Lines changed: 15 additions & 13 deletions

File tree

‎packages/objectql/src/engine.ts‎

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ import { deriveViewContainerObject } from '@objectstack/metadata/view-container'
262262
// registrar and `os validate` both call.
263263
import { viewContainerNameRefusal } from './view-container-name-refusal.js';
264264
import { bindHooksToEngine } from './hook-binder.js';
265-
import { validateRecordInScope, normalizeMultiValueFields, normalizeBlankTypedValues, normalizeNumericStringValues, coerceBooleanFields, ValidationError, buildFieldError, resolveFieldLabel, valueShapePostureSetByEnv, mediaPostureSetByEnv, isScannableValueShapeField, valueShapeStrictEffective, mediaStrictEffective } from './validation/record-validator.js';
265+
import { validateRecord, validateRecordInScope, normalizeMultiValueFields, normalizeBlankTypedValues, normalizeNumericStringValues, coerceBooleanFields, ValidationError, buildFieldError, resolveFieldLabel, valueShapePostureSetByEnv, mediaPostureSetByEnv, isScannableValueShapeField, valueShapeStrictEffective, mediaStrictEffective } from './validation/record-validator.js';
266266
import type { AdmittedValueShapeViolation, AdmittedValueShapeViolationSink } from './validation/record-validator.js';
267267
import type { RelatedFieldBinding, RelatedRecordBinding } from './validation/rule-validator.js';
268268
import { collectPredicateRelationships, evaluateValidationRules, optionVisibilityReadsPermissions, readsPermissionPredicate, referentialClearBinding, needsPriorRecord, stripReadonlyWhenFields, stripReadonlyWhenFieldsMulti, hasReadonlyWhenInPayload, hasParentScopedReadonlyWhenInPayload, hasParentScopedRequiredWhen, stripReadonlyFields, stripRuntimeOwnedFields, staticReadonlyInsertSubject, preserveAuditIgnoredOnInsertWarning } from './validation/rule-validator.js';
@@ -14885,13 +14885,14 @@ export class ObjectQL implements IObjectQLEngine {
1488514885
// secret channel (which carries the secret-arm refusal).
1488614886
this.refuseEmptyPasswordFields(object, hookContext.input.data as Record<string, unknown>);
1488714887
await this.encryptSecretFields(object, hookContext.input.data as Record<string, unknown>, opCtx.context, hookContext.input.options);
14888-
// [#21663] `'skip'`: the readonly strip has NOT run yet, so a
14889-
// readonly value here may be a caller's the strip is about to
14890-
// drop — judged, a whole-record write-back echoing a legacy
14891-
// stored value would become a refusal. Readonly values are
14892-
// judged after the strip (`'only'`, below).
14888+
// [#21663] Scope `'skip'` — the public `validateRecord` IS that
14889+
// scope: the readonly strip has NOT run yet, so a readonly value
14890+
// here may be a caller's the strip is about to drop — judged, a
14891+
// whole-record write-back echoing a legacy stored value would
14892+
// become a refusal. Readonly values are judged after the strip
14893+
// (`validateRecordInScope(…, 'only')`, below).
1489314894
normalizeMultiValueFields(updateSchema, hookContext.input.data as Record<string, unknown>, 'skip');
14894-
validateRecordInScope(updateSchema, hookContext.input.data as Record<string, unknown>, 'update', 'skip', { mediaValueShapeStrict, valueShapeStrict, messages: updateMsgCtx, onAdmittedValueShapeViolation });
14895+
validateRecord(updateSchema, hookContext.input.data as Record<string, unknown>, 'update', { mediaValueShapeStrict, valueShapeStrict, messages: updateMsgCtx, onAdmittedValueShapeViolation });
1489514896
// [#5284] Demand-driven, and the demand is asked PER OBJECT.
1489614897
//
1489714898
// This gate used to ask `this.hooks.get('afterUpdate').length > 0`
@@ -15219,13 +15220,14 @@ export class ObjectQL implements IObjectQLEngine {
1521915220
// secret channel (which carries the secret-arm refusal).
1522015221
this.refuseEmptyPasswordFields(object, hookContext.input.data as Record<string, unknown>);
1522115222
await this.encryptSecretFields(object, hookContext.input.data as Record<string, unknown>, opCtx.context, hookContext.input.options);
15222-
// [#21663] `'skip'`: the readonly strip has NOT run yet, so a
15223-
// readonly value here may be a caller's the strip is about to
15224-
// drop — judged, a whole-record write-back echoing a legacy
15225-
// stored value would become a refusal. Readonly values are
15226-
// judged after the strip (`'only'`, below).
15223+
// [#21663] Scope `'skip'` — the public `validateRecord` IS that
15224+
// scope: the readonly strip has NOT run yet, so a readonly value
15225+
// here may be a caller's the strip is about to drop — judged, a
15226+
// whole-record write-back echoing a legacy stored value would
15227+
// become a refusal. Readonly values are judged after the strip
15228+
// (`validateRecordInScope(…, 'only')`, below).
1522715229
normalizeMultiValueFields(updateSchema, hookContext.input.data as Record<string, unknown>, 'skip');
15228-
validateRecordInScope(updateSchema, hookContext.input.data as Record<string, unknown>, 'update', 'skip', { mediaValueShapeStrict, valueShapeStrict, messages: updateMsgCtx, onAdmittedValueShapeViolation });
15230+
validateRecord(updateSchema, hookContext.input.data as Record<string, unknown>, 'update', { mediaValueShapeStrict, valueShapeStrict, messages: updateMsgCtx, onAdmittedValueShapeViolation });
1522915231
// [#2982] The middleware-composed AST — asserted present and
1523015232
// bound to the memoized row read in the pre-phase above, so the
1523115233
// injected row-scoping (RLS write filter, sharing's

0 commit comments

Comments
 (0)