@objectstack/lint 14.3.0 → 14.6.0
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/dist/index.cjs +61 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -2
- package/dist/index.d.ts +10 -2
- package/dist/index.js +58 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.d.cts
CHANGED
|
@@ -397,6 +397,9 @@ declare const SECURITY_ANCHOR_HIGH_PRIVILEGE = "security-anchor-high-privilege";
|
|
|
397
397
|
declare const SECURITY_ROLE_WORD = "security-role-word";
|
|
398
398
|
declare const SECURITY_BOOK_AUDIENCE_UNKNOWN_SET = "security-book-audience-unknown-set";
|
|
399
399
|
declare const SECURITY_PRIVATE_NO_READSCOPE = "security-private-no-readscope";
|
|
400
|
+
declare const SECURITY_MASTER_DETAIL_UNGRANTED = "security-master-detail-ungranted";
|
|
401
|
+
declare const SECURITY_GRANT_EXPIRED_AT_AUTHORING = "security-grant-expired-at-authoring";
|
|
402
|
+
declare const SECURITY_DELEGATION_MISSING_REASON = "security-delegation-missing-reason";
|
|
400
403
|
type SecuritySeverity = 'error' | 'warning' | 'info';
|
|
401
404
|
interface SecurityFinding {
|
|
402
405
|
severity: SecuritySeverity;
|
|
@@ -415,8 +418,13 @@ type AnyRec$1 = Record<string, unknown>;
|
|
|
415
418
|
/**
|
|
416
419
|
* Validate the security posture of a stack. Returns findings (empty = clean).
|
|
417
420
|
* `error` findings gate the build in `os compile`; `info` is advisory.
|
|
421
|
+
*
|
|
422
|
+
* `opts.nowMs` injects the clock for the ADR-0091 authoring-time expiry rule
|
|
423
|
+
* (tests); production callers omit it.
|
|
418
424
|
*/
|
|
419
|
-
declare function validateSecurityPosture(stack: AnyRec$1
|
|
425
|
+
declare function validateSecurityPosture(stack: AnyRec$1, opts?: {
|
|
426
|
+
nowMs?: number;
|
|
427
|
+
}): SecurityFinding[];
|
|
420
428
|
|
|
421
429
|
/**
|
|
422
430
|
* [ADR-0090 D6] Access-matrix snapshot — authoring-time companion to the
|
|
@@ -442,4 +450,4 @@ declare function buildAccessMatrix(stack: AnyRec): AccessMatrix;
|
|
|
442
450
|
*/
|
|
443
451
|
declare function diffAccessMatrix(before: AccessMatrix, after: AccessMatrix): string[];
|
|
444
452
|
|
|
445
|
-
export { APPROVAL_APPROVER_TYPE_UNKNOWN, APPROVAL_ESCALATION_REASSIGN_NO_TARGET, APPROVAL_ROLE_NOT_MEMBERSHIP_TIER, type ApprovalApproverFinding, type ApprovalApproverSeverity, CAPABILITY_REFERENCE_UNKNOWN, CHART_CONFIG_MISSING, CHART_FIELD_UNKNOWN, type CapabilityRefFinding, type CapabilityRefSeverity, type ExprIssue, FIELD_GROUP_EMPTY, FIELD_GROUP_UNDECLARED, FORM_COLSPAN_ABSOLUTE, FORM_FIELD_UNKNOWN, type FormLayoutFinding, type FormLayoutSeverity, type JsxPageFinding, type JsxPageSeverity, LIST_VIEW_FILTERS_IN_VIEWS_MODE, type ListViewModeFinding, type ListViewModeSeverity, MEASURE_AGGREGATE_INCOHERENT, PAGE_SOURCE_CLASSNAME, type ReactPageFinding, type ReactPageSeverity, type ReactPropFinding, type ReactPropSeverity, type RecordTitleFinding, type RecordTitleSeverity, SECURITY_ANCHOR_HIGH_PRIVILEGE, SECURITY_BOOK_AUDIENCE_UNKNOWN_SET, SECURITY_EXTERNAL_WIDER, SECURITY_OWD_ALIAS, SECURITY_OWD_UNSET, SECURITY_PRIVATE_NO_READSCOPE, SECURITY_ROLE_WORD, SECURITY_WILDCARD_VAMA, SEMANTIC_ROLE_FIELD_UNKNOWN, STYLE_CLASSNAME_TAILWIND, STYLE_NODE_MISSING_ID, STYLE_RESPONSIVE_NO_BASE, STYLE_UNKNOWN_CSS_PROPERTY, STYLE_UNKNOWN_TOKEN, type SecurityFinding, type SecuritySeverity, type SemanticRoleFinding, type SemanticRoleSeverity, type SourceStyleFinding, type SourceStyleSeverity, type StyleFinding, type StyleSeverity, TABLE_COUNT_ONLY, TITLE_FORMAT_RETIRED, TITLE_UNRESOLVABLE, WIDGET_DATASET_UNKNOWN, WIDGET_DIMENSION_UNKNOWN, WIDGET_MEASURE_UNKNOWN, type WidgetBindingFinding, type WidgetBindingSeverity, buildAccessMatrix, diffAccessMatrix, validateApprovalApprovers, validateCapabilityReferences, validateFormLayout, validateJsxPages, validateListViewMode, validatePageSourceStyling, validateReactPageProps, validateReactPages, validateRecordTitle, validateResponsiveStyles, validateSecurityPosture, validateSemanticRoles, validateStackExpressions, validateWidgetBindings };
|
|
453
|
+
export { APPROVAL_APPROVER_TYPE_UNKNOWN, APPROVAL_ESCALATION_REASSIGN_NO_TARGET, APPROVAL_ROLE_NOT_MEMBERSHIP_TIER, type ApprovalApproverFinding, type ApprovalApproverSeverity, CAPABILITY_REFERENCE_UNKNOWN, CHART_CONFIG_MISSING, CHART_FIELD_UNKNOWN, type CapabilityRefFinding, type CapabilityRefSeverity, type ExprIssue, FIELD_GROUP_EMPTY, FIELD_GROUP_UNDECLARED, FORM_COLSPAN_ABSOLUTE, FORM_FIELD_UNKNOWN, type FormLayoutFinding, type FormLayoutSeverity, type JsxPageFinding, type JsxPageSeverity, LIST_VIEW_FILTERS_IN_VIEWS_MODE, type ListViewModeFinding, type ListViewModeSeverity, MEASURE_AGGREGATE_INCOHERENT, PAGE_SOURCE_CLASSNAME, type ReactPageFinding, type ReactPageSeverity, type ReactPropFinding, type ReactPropSeverity, type RecordTitleFinding, type RecordTitleSeverity, SECURITY_ANCHOR_HIGH_PRIVILEGE, SECURITY_BOOK_AUDIENCE_UNKNOWN_SET, SECURITY_DELEGATION_MISSING_REASON, SECURITY_EXTERNAL_WIDER, SECURITY_GRANT_EXPIRED_AT_AUTHORING, SECURITY_MASTER_DETAIL_UNGRANTED, SECURITY_OWD_ALIAS, SECURITY_OWD_UNSET, SECURITY_PRIVATE_NO_READSCOPE, SECURITY_ROLE_WORD, SECURITY_WILDCARD_VAMA, SEMANTIC_ROLE_FIELD_UNKNOWN, STYLE_CLASSNAME_TAILWIND, STYLE_NODE_MISSING_ID, STYLE_RESPONSIVE_NO_BASE, STYLE_UNKNOWN_CSS_PROPERTY, STYLE_UNKNOWN_TOKEN, type SecurityFinding, type SecuritySeverity, type SemanticRoleFinding, type SemanticRoleSeverity, type SourceStyleFinding, type SourceStyleSeverity, type StyleFinding, type StyleSeverity, TABLE_COUNT_ONLY, TITLE_FORMAT_RETIRED, TITLE_UNRESOLVABLE, WIDGET_DATASET_UNKNOWN, WIDGET_DIMENSION_UNKNOWN, WIDGET_MEASURE_UNKNOWN, type WidgetBindingFinding, type WidgetBindingSeverity, buildAccessMatrix, diffAccessMatrix, validateApprovalApprovers, validateCapabilityReferences, validateFormLayout, validateJsxPages, validateListViewMode, validatePageSourceStyling, validateReactPageProps, validateReactPages, validateRecordTitle, validateResponsiveStyles, validateSecurityPosture, validateSemanticRoles, validateStackExpressions, validateWidgetBindings };
|
package/dist/index.d.ts
CHANGED
|
@@ -397,6 +397,9 @@ declare const SECURITY_ANCHOR_HIGH_PRIVILEGE = "security-anchor-high-privilege";
|
|
|
397
397
|
declare const SECURITY_ROLE_WORD = "security-role-word";
|
|
398
398
|
declare const SECURITY_BOOK_AUDIENCE_UNKNOWN_SET = "security-book-audience-unknown-set";
|
|
399
399
|
declare const SECURITY_PRIVATE_NO_READSCOPE = "security-private-no-readscope";
|
|
400
|
+
declare const SECURITY_MASTER_DETAIL_UNGRANTED = "security-master-detail-ungranted";
|
|
401
|
+
declare const SECURITY_GRANT_EXPIRED_AT_AUTHORING = "security-grant-expired-at-authoring";
|
|
402
|
+
declare const SECURITY_DELEGATION_MISSING_REASON = "security-delegation-missing-reason";
|
|
400
403
|
type SecuritySeverity = 'error' | 'warning' | 'info';
|
|
401
404
|
interface SecurityFinding {
|
|
402
405
|
severity: SecuritySeverity;
|
|
@@ -415,8 +418,13 @@ type AnyRec$1 = Record<string, unknown>;
|
|
|
415
418
|
/**
|
|
416
419
|
* Validate the security posture of a stack. Returns findings (empty = clean).
|
|
417
420
|
* `error` findings gate the build in `os compile`; `info` is advisory.
|
|
421
|
+
*
|
|
422
|
+
* `opts.nowMs` injects the clock for the ADR-0091 authoring-time expiry rule
|
|
423
|
+
* (tests); production callers omit it.
|
|
418
424
|
*/
|
|
419
|
-
declare function validateSecurityPosture(stack: AnyRec$1
|
|
425
|
+
declare function validateSecurityPosture(stack: AnyRec$1, opts?: {
|
|
426
|
+
nowMs?: number;
|
|
427
|
+
}): SecurityFinding[];
|
|
420
428
|
|
|
421
429
|
/**
|
|
422
430
|
* [ADR-0090 D6] Access-matrix snapshot — authoring-time companion to the
|
|
@@ -442,4 +450,4 @@ declare function buildAccessMatrix(stack: AnyRec): AccessMatrix;
|
|
|
442
450
|
*/
|
|
443
451
|
declare function diffAccessMatrix(before: AccessMatrix, after: AccessMatrix): string[];
|
|
444
452
|
|
|
445
|
-
export { APPROVAL_APPROVER_TYPE_UNKNOWN, APPROVAL_ESCALATION_REASSIGN_NO_TARGET, APPROVAL_ROLE_NOT_MEMBERSHIP_TIER, type ApprovalApproverFinding, type ApprovalApproverSeverity, CAPABILITY_REFERENCE_UNKNOWN, CHART_CONFIG_MISSING, CHART_FIELD_UNKNOWN, type CapabilityRefFinding, type CapabilityRefSeverity, type ExprIssue, FIELD_GROUP_EMPTY, FIELD_GROUP_UNDECLARED, FORM_COLSPAN_ABSOLUTE, FORM_FIELD_UNKNOWN, type FormLayoutFinding, type FormLayoutSeverity, type JsxPageFinding, type JsxPageSeverity, LIST_VIEW_FILTERS_IN_VIEWS_MODE, type ListViewModeFinding, type ListViewModeSeverity, MEASURE_AGGREGATE_INCOHERENT, PAGE_SOURCE_CLASSNAME, type ReactPageFinding, type ReactPageSeverity, type ReactPropFinding, type ReactPropSeverity, type RecordTitleFinding, type RecordTitleSeverity, SECURITY_ANCHOR_HIGH_PRIVILEGE, SECURITY_BOOK_AUDIENCE_UNKNOWN_SET, SECURITY_EXTERNAL_WIDER, SECURITY_OWD_ALIAS, SECURITY_OWD_UNSET, SECURITY_PRIVATE_NO_READSCOPE, SECURITY_ROLE_WORD, SECURITY_WILDCARD_VAMA, SEMANTIC_ROLE_FIELD_UNKNOWN, STYLE_CLASSNAME_TAILWIND, STYLE_NODE_MISSING_ID, STYLE_RESPONSIVE_NO_BASE, STYLE_UNKNOWN_CSS_PROPERTY, STYLE_UNKNOWN_TOKEN, type SecurityFinding, type SecuritySeverity, type SemanticRoleFinding, type SemanticRoleSeverity, type SourceStyleFinding, type SourceStyleSeverity, type StyleFinding, type StyleSeverity, TABLE_COUNT_ONLY, TITLE_FORMAT_RETIRED, TITLE_UNRESOLVABLE, WIDGET_DATASET_UNKNOWN, WIDGET_DIMENSION_UNKNOWN, WIDGET_MEASURE_UNKNOWN, type WidgetBindingFinding, type WidgetBindingSeverity, buildAccessMatrix, diffAccessMatrix, validateApprovalApprovers, validateCapabilityReferences, validateFormLayout, validateJsxPages, validateListViewMode, validatePageSourceStyling, validateReactPageProps, validateReactPages, validateRecordTitle, validateResponsiveStyles, validateSecurityPosture, validateSemanticRoles, validateStackExpressions, validateWidgetBindings };
|
|
453
|
+
export { APPROVAL_APPROVER_TYPE_UNKNOWN, APPROVAL_ESCALATION_REASSIGN_NO_TARGET, APPROVAL_ROLE_NOT_MEMBERSHIP_TIER, type ApprovalApproverFinding, type ApprovalApproverSeverity, CAPABILITY_REFERENCE_UNKNOWN, CHART_CONFIG_MISSING, CHART_FIELD_UNKNOWN, type CapabilityRefFinding, type CapabilityRefSeverity, type ExprIssue, FIELD_GROUP_EMPTY, FIELD_GROUP_UNDECLARED, FORM_COLSPAN_ABSOLUTE, FORM_FIELD_UNKNOWN, type FormLayoutFinding, type FormLayoutSeverity, type JsxPageFinding, type JsxPageSeverity, LIST_VIEW_FILTERS_IN_VIEWS_MODE, type ListViewModeFinding, type ListViewModeSeverity, MEASURE_AGGREGATE_INCOHERENT, PAGE_SOURCE_CLASSNAME, type ReactPageFinding, type ReactPageSeverity, type ReactPropFinding, type ReactPropSeverity, type RecordTitleFinding, type RecordTitleSeverity, SECURITY_ANCHOR_HIGH_PRIVILEGE, SECURITY_BOOK_AUDIENCE_UNKNOWN_SET, SECURITY_DELEGATION_MISSING_REASON, SECURITY_EXTERNAL_WIDER, SECURITY_GRANT_EXPIRED_AT_AUTHORING, SECURITY_MASTER_DETAIL_UNGRANTED, SECURITY_OWD_ALIAS, SECURITY_OWD_UNSET, SECURITY_PRIVATE_NO_READSCOPE, SECURITY_ROLE_WORD, SECURITY_WILDCARD_VAMA, SEMANTIC_ROLE_FIELD_UNKNOWN, STYLE_CLASSNAME_TAILWIND, STYLE_NODE_MISSING_ID, STYLE_RESPONSIVE_NO_BASE, STYLE_UNKNOWN_CSS_PROPERTY, STYLE_UNKNOWN_TOKEN, type SecurityFinding, type SecuritySeverity, type SemanticRoleFinding, type SemanticRoleSeverity, type SourceStyleFinding, type SourceStyleSeverity, type StyleFinding, type StyleSeverity, TABLE_COUNT_ONLY, TITLE_FORMAT_RETIRED, TITLE_UNRESOLVABLE, WIDGET_DATASET_UNKNOWN, WIDGET_DIMENSION_UNKNOWN, WIDGET_MEASURE_UNKNOWN, type WidgetBindingFinding, type WidgetBindingSeverity, buildAccessMatrix, diffAccessMatrix, validateApprovalApprovers, validateCapabilityReferences, validateFormLayout, validateJsxPages, validateListViewMode, validatePageSourceStyling, validateReactPageProps, validateReactPages, validateRecordTitle, validateResponsiveStyles, validateSecurityPosture, validateSemanticRoles, validateStackExpressions, validateWidgetBindings };
|
package/dist/index.js
CHANGED
|
@@ -1391,6 +1391,9 @@ var SECURITY_ROLE_WORD = "security-role-word";
|
|
|
1391
1391
|
var SECURITY_BOOK_AUDIENCE_UNKNOWN_SET = "security-book-audience-unknown-set";
|
|
1392
1392
|
var SECURITY_PRIVATE_NO_READSCOPE = "security-private-no-readscope";
|
|
1393
1393
|
var SECURITY_MASTER_DETAIL_UNGRANTED = "security-master-detail-ungranted";
|
|
1394
|
+
var SECURITY_FLS_UNQUALIFIED_KEY = "security-fls-unqualified-key";
|
|
1395
|
+
var SECURITY_GRANT_EXPIRED_AT_AUTHORING = "security-grant-expired-at-authoring";
|
|
1396
|
+
var SECURITY_DELEGATION_MISSING_REASON = "security-delegation-missing-reason";
|
|
1394
1397
|
var CANONICAL_OWD = ["private", "public_read", "public_read_write", "controlled_by_parent"];
|
|
1395
1398
|
var OWD_ALIAS_FIX = {
|
|
1396
1399
|
read: "public_read",
|
|
@@ -1439,7 +1442,7 @@ function firstMasterDetailField(obj) {
|
|
|
1439
1442
|
function grantsObjectAccess(p) {
|
|
1440
1443
|
return p.allowRead === true || p.allowCreate === true || p.allowEdit === true || p.allowDelete === true || p.viewAllRecords === true || p.modifyAllRecords === true;
|
|
1441
1444
|
}
|
|
1442
|
-
function validateSecurityPosture(stack) {
|
|
1445
|
+
function validateSecurityPosture(stack, opts) {
|
|
1443
1446
|
const findings = [];
|
|
1444
1447
|
if (!stack || typeof stack !== "object") return findings;
|
|
1445
1448
|
const objects = asArray14(stack.objects);
|
|
@@ -1509,6 +1512,18 @@ function validateSecurityPosture(stack) {
|
|
|
1509
1512
|
const psName = typeof ps.name === "string" ? ps.name : `(permission set ${i})`;
|
|
1510
1513
|
const psPath = `permissions[${i}]`;
|
|
1511
1514
|
const objectsMap = ps.objects && typeof ps.objects === "object" ? ps.objects : {};
|
|
1515
|
+
const flsMap = ps.fields && typeof ps.fields === "object" ? ps.fields : {};
|
|
1516
|
+
for (const flsKey of Object.keys(flsMap)) {
|
|
1517
|
+
if (flsKey.includes(".")) continue;
|
|
1518
|
+
findings.push({
|
|
1519
|
+
severity: "error",
|
|
1520
|
+
rule: SECURITY_FLS_UNQUALIFIED_KEY,
|
|
1521
|
+
where: `permission set "${psName}"`,
|
|
1522
|
+
path: `${psPath}.fields["${flsKey}"]`,
|
|
1523
|
+
message: `field-permission key '${flsKey}' is not object-qualified \u2014 the runtime matches FLS keys by '<object>.<field>' prefix, so a bare key is silently IGNORED and the declared masking never enforces.`,
|
|
1524
|
+
hint: `Qualify the key with its object, e.g. 'crm_opportunity.${flsKey}': { readable: true, editable: false }.`
|
|
1525
|
+
});
|
|
1526
|
+
}
|
|
1512
1527
|
const wildcard = objectsMap["*"];
|
|
1513
1528
|
if (wildcard && (wildcard.viewAllRecords === true || wildcard.modifyAllRecords === true)) {
|
|
1514
1529
|
findings.push({
|
|
@@ -1660,6 +1675,45 @@ function validateSecurityPosture(stack) {
|
|
|
1660
1675
|
}
|
|
1661
1676
|
}
|
|
1662
1677
|
}
|
|
1678
|
+
const GRANT_SEED_OBJECTS = /* @__PURE__ */ new Set(["sys_user_position", "sys_user_permission_set"]);
|
|
1679
|
+
const nowMs = opts?.nowMs ?? Date.now();
|
|
1680
|
+
for (const [i, seed] of asArray14(stack.data).entries()) {
|
|
1681
|
+
const seedObject = typeof seed.object === "string" ? seed.object : "";
|
|
1682
|
+
if (!GRANT_SEED_OBJECTS.has(seedObject)) continue;
|
|
1683
|
+
const records = Array.isArray(seed.records) ? seed.records : [];
|
|
1684
|
+
for (let j = 0; j < records.length; j++) {
|
|
1685
|
+
const rec = records[j] ?? {};
|
|
1686
|
+
const where = `seed "${seedObject}" record #${j}`;
|
|
1687
|
+
const until = rec.valid_until;
|
|
1688
|
+
if (until != null && until !== "") {
|
|
1689
|
+
const ms = typeof until === "number" ? until < 1e12 ? until * 1e3 : until : until instanceof Date ? until.getTime() : typeof until === "string" ? Date.parse(until) : Number.NaN;
|
|
1690
|
+
if (Number.isNaN(ms) || ms <= nowMs) {
|
|
1691
|
+
findings.push({
|
|
1692
|
+
severity: "error",
|
|
1693
|
+
rule: SECURITY_GRANT_EXPIRED_AT_AUTHORING,
|
|
1694
|
+
where,
|
|
1695
|
+
path: `data[${i}].records[${j}].valid_until`,
|
|
1696
|
+
message: Number.isNaN(ms) ? `valid_until ${JSON.stringify(until)} is not a parseable timestamp \u2014 the resolver fails closed (ADR-0091 D2), so this grant will NEVER be active.` : `valid_until ${JSON.stringify(until)} is already in the past \u2014 this grant is expired at authoring time and will never resolve (ADR-0091 D2 filters it fail-closed).`,
|
|
1697
|
+
hint: `Set valid_until to a future instant (ISO-8601 UTC), or drop the column for an unbounded grant. If the row is a historical record, it belongs in audit history, not seed data.`
|
|
1698
|
+
});
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
const delegatedFrom = rec.delegated_from;
|
|
1702
|
+
if (delegatedFrom != null && delegatedFrom !== "") {
|
|
1703
|
+
const reason = rec.reason;
|
|
1704
|
+
if (typeof reason !== "string" || reason.trim().length === 0) {
|
|
1705
|
+
findings.push({
|
|
1706
|
+
severity: "error",
|
|
1707
|
+
rule: SECURITY_DELEGATION_MISSING_REASON,
|
|
1708
|
+
where,
|
|
1709
|
+
path: `data[${i}].records[${j}].reason`,
|
|
1710
|
+
message: `delegation row (delegated_from = ${JSON.stringify(delegatedFrom)}) has no reason. ADR-0091 D3 requires a mandatory reason on every delegation for the dual audit trail (granted_by = writer, delegated_from = authority source, reason = why).`,
|
|
1711
|
+
hint: `Add reason: 'vacation stand-in for \u5F20\u4E09, 2026-08-01..15' (free text, required).`
|
|
1712
|
+
});
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1663
1717
|
return findings;
|
|
1664
1718
|
}
|
|
1665
1719
|
|
|
@@ -1767,7 +1821,10 @@ export {
|
|
|
1767
1821
|
PAGE_SOURCE_CLASSNAME,
|
|
1768
1822
|
SECURITY_ANCHOR_HIGH_PRIVILEGE,
|
|
1769
1823
|
SECURITY_BOOK_AUDIENCE_UNKNOWN_SET,
|
|
1824
|
+
SECURITY_DELEGATION_MISSING_REASON,
|
|
1770
1825
|
SECURITY_EXTERNAL_WIDER,
|
|
1826
|
+
SECURITY_GRANT_EXPIRED_AT_AUTHORING,
|
|
1827
|
+
SECURITY_MASTER_DETAIL_UNGRANTED,
|
|
1771
1828
|
SECURITY_OWD_ALIAS,
|
|
1772
1829
|
SECURITY_OWD_UNSET,
|
|
1773
1830
|
SECURITY_PRIVATE_NO_READSCOPE,
|