@company-semantics/contracts 9.2.0 → 11.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@company-semantics/contracts",
3
- "version": "9.2.0",
3
+ "version": "11.0.0",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -115,7 +115,7 @@
115
115
  "zod": "^4.4.3"
116
116
  },
117
117
  "devDependencies": {
118
- "@types/node": "^22.19.19",
118
+ "@types/node": "^25.9.2",
119
119
  "husky": "^9.1.7",
120
120
  "lint-staged": "^17.0.7",
121
121
  "markdownlint-cli2": "^0.22.1",
@@ -74,6 +74,12 @@ export const CompanyMdDocResponseSchema = z.object({
74
74
  title: z.string(),
75
75
  level: z.enum(["root", "department", "team", "context"]),
76
76
  content: z.string(),
77
+ /**
78
+ * When `true`, `content` is the redacted empty body (`''`) returned to a
79
+ * metadata-only (meta-tier) viewer who administers the doc but may not read
80
+ * its body (ADR-BE-245). Omitted/`false` on the normal full-content path.
81
+ */
82
+ contentRedacted: z.boolean().optional(),
77
83
  visibility: z.enum(["private", "unit", "org"]),
78
84
  parentId: z.string().nullable(),
79
85
  owningUnitId: z.string().nullable(),
package/src/index.ts CHANGED
@@ -644,7 +644,6 @@ export {
644
644
  resolveScope,
645
645
  toQueryKey,
646
646
  fromQueryKey,
647
- resourceRelationships,
648
647
  matchesResourceKey,
649
648
  } from "./resource-keys";
650
649
 
@@ -119,6 +119,12 @@ export interface CompanyMdTreeNode extends CompanyMdNodeIdentity {
119
119
 
120
120
  export interface CompanyMdDocCore extends CompanyMdNodeIdentity {
121
121
  readonly content: string;
122
+ /**
123
+ * When `true`, `content` is the redacted empty body (`''`) returned to a
124
+ * metadata-only (meta-tier) viewer who administers the doc but may not read
125
+ * its body (ADR-BE-245). Omitted/`false` on the normal full-content path.
126
+ */
127
+ readonly contentRedacted?: boolean;
122
128
  }
123
129
 
124
130
  export interface CompanyMdDocCollaborators {
@@ -1,18 +1,25 @@
1
1
  /**
2
2
  * Permission Access Levels
3
3
  *
4
- * Canonical four-level access vocabulary for object permissions across
5
- * Company Semantics, modeled on the Google-Docs four-level scheme.
4
+ * Canonical access vocabulary for object permissions across
5
+ * Company Semantics, modeled on the Google-Docs four-level scheme plus a
6
+ * weakest `meta` tier below `viewer`.
6
7
  *
7
8
  * Authority: ADR-CTRL-085 (Rights Table). See ADR-CTRL-084 for how these
8
9
  * levels are materialized into `effective_acl_grants`, and ADR-CTRL-086 for
9
10
  * the aggregation rule (most-permissive across sources).
10
11
  *
11
12
  * The commenter level is currently a stub — see ADR-CTRL-087.
13
+ *
14
+ * `meta` is the metadata-only tier used for org-admin lifecycle access
15
+ * (ADR-BE-245). It is materialized/derived only — never an explicit
16
+ * `acl_grants` value — and sits strictly below `viewer`, so
17
+ * `isAtLeast('meta', 'viewer') === false`.
12
18
  */
13
19
  import { z } from "zod";
14
20
 
15
21
  export const ACCESS_LEVELS = [
22
+ "meta",
16
23
  "owner",
17
24
  "editor",
18
25
  "commenter",
@@ -27,10 +34,11 @@ export const AccessLevelSchema = z.enum(ACCESS_LEVELS);
27
34
  * Used by `highestGrant()` in AUTH-006 (PRD-00674) to aggregate across sources.
28
35
  */
29
36
  export const ACCESS_LEVEL_ORDER: Record<AccessLevel, number> = {
30
- viewer: 0,
31
- commenter: 1,
32
- editor: 2,
33
- owner: 3,
37
+ meta: 0,
38
+ viewer: 1,
39
+ commenter: 2,
40
+ editor: 3,
41
+ owner: 4,
34
42
  };
35
43
 
36
44
  /**
@@ -251,34 +251,6 @@ export function fromQueryKey(queryKey: readonly string[]): ResourceKey {
251
251
  throw new Error(`Unknown resource type in query key: '${type}'`);
252
252
  }
253
253
 
254
- /**
255
- * Bidirectional resource relationships.
256
- * TanStack does NOT support prefix matching across different key shapes.
257
- * When invalidating a collection, we must also invalidate related identity entries (and vice versa).
258
- */
259
- export const resourceRelationships: Record<string, string[]> = {
260
- members: ["member"],
261
- member: ["members"],
262
- departments: ["department"],
263
- department: ["departments"],
264
- chats: ["chat"],
265
- chat: ["chats"],
266
- teams: ["team"],
267
- team: ["teams"],
268
- companyMdDocs: ["companyMdDoc"],
269
- companyMdDoc: ["companyMdDocs"],
270
- // OrgUnit: reparent/create/archive invalidates the tree view of the whole org;
271
- // membership mutations invalidate the unit + its memberships list.
272
- orgTree: ["orgUnit", "orgUnitChildren", "orgUnitAncestors"],
273
- orgUnit: ["orgTree"],
274
- orgUnitChildren: ["orgTree"],
275
- orgUnitAncestors: ["orgTree"],
276
- // Subtree manage is driven by memberships (ADR-BE-151); mutating memberships
277
- // invalidates both the direct roster and the effective-managers read.
278
- orgUnitMemberships: ["orgUnit", "orgUnitPermissions"],
279
- orgUnitPermissions: ["orgUnitMemberships"],
280
- };
281
-
282
254
  /**
283
255
  * Strict predicate for matching resource keys.
284
256
  * Compares type + scope fields exactly. No partial matching. No loose comparisons.