@@ -262,7 +262,7 @@ import { deriveViewContainerObject } from '@objectstack/metadata/view-container'
262262// registrar and `os validate` both call.
263263import { viewContainerNameRefusal } from './view-container-name-refusal.js';
264264import { 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';
266266import type { AdmittedValueShapeViolation, AdmittedValueShapeViolationSink } from './validation/record-validator.js';
267267import type { RelatedFieldBinding, RelatedRecordBinding } from './validation/rule-validator.js';
268268import { 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