@sparkelf/dsh-knowledge-base 0.1.2 → 0.1.3
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/README.md +63 -0
- package/lib/client.js +563 -616
- package/lib/client.js.map +1 -1
- package/lib/types/client/KnowledgeHome.d.ts +11 -0
- package/lib/types/client/KnowledgePermissionOverview.d.ts +0 -4
- package/lib/types/client/locales.d.ts +1 -0
- package/lib/types/client/mineScope.d.ts +79 -0
- package/lib/types/client/roleSummary.d.ts +12 -5
- package/lib/types/client/shareRelations.d.ts +39 -1
- package/package.json +1 -1
|
@@ -37,6 +37,17 @@ export interface KnowledgeHomeProps {
|
|
|
37
37
|
departmentCode?: string;
|
|
38
38
|
/** The caller's own department name; the code stands in when this is absent. */
|
|
39
39
|
departmentName?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Whether the Host verified this caller may manage grants.
|
|
42
|
+
*
|
|
43
|
+
* This is the ONLY per-caller permission answer the client receives. There is no
|
|
44
|
+
* per-path "may I write this" route: `grants` is admin-scoped and the list route
|
|
45
|
+
* reports visibility, not writability. So the "Owned by me" tab uses this as its
|
|
46
|
+
* whole answer for the shared buckets -- an administrator sees the shared documents
|
|
47
|
+
* there, a plain reader does not -- and marks the rows whose answer it could not
|
|
48
|
+
* narrow rather than pretending either way.
|
|
49
|
+
*/
|
|
50
|
+
canManageGrants?: boolean;
|
|
40
51
|
/**
|
|
41
52
|
* The tab whose card should take focus on mount.
|
|
42
53
|
*
|
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
* @module @sparkelf/dsh-knowledge-base/client/KnowledgePermissionOverview
|
|
20
20
|
*/
|
|
21
21
|
import type { GrantView, KnowledgeGrantSubjectType } from '../api.ts';
|
|
22
|
-
import { type RoleSummary } from './roleSummary.ts';
|
|
23
22
|
/** Which reading of the grant table the tabs are showing. */
|
|
24
23
|
export type OverviewTab = 'person' | 'role' | 'resource';
|
|
25
24
|
/** Copy for the overview, supplied by the caller's locale record. */
|
|
@@ -55,7 +54,6 @@ export interface OverviewCopy {
|
|
|
55
54
|
pathsHeld: (count: number) => string;
|
|
56
55
|
rolesHeld: string;
|
|
57
56
|
actionsHeld: string;
|
|
58
|
-
builtInRoles: string;
|
|
59
57
|
noActions: string;
|
|
60
58
|
/** Accessible name for the tab strip, for readers who arrive at it by keyboard. */
|
|
61
59
|
tabsLabel: string;
|
|
@@ -118,8 +116,6 @@ export interface KnowledgePermissionOverviewProps {
|
|
|
118
116
|
kind: 'unavailable';
|
|
119
117
|
reason: string;
|
|
120
118
|
};
|
|
121
|
-
/** Built-in role summaries, so the person view can explain what a role means. */
|
|
122
|
-
roles?: readonly RoleSummary[];
|
|
123
119
|
/** Locale copy. */
|
|
124
120
|
copy: OverviewCopy;
|
|
125
121
|
/**
|
|
@@ -342,6 +342,7 @@ export declare const en: {
|
|
|
342
342
|
readonly 'step.sshfs-mount': "Mount the share over SSHFS";
|
|
343
343
|
readonly 'step.sshfs-verify': "Verify the SSHFS mount";
|
|
344
344
|
readonly deployLocalOnly: "Deployment steps run on a remote host. This workspace stores documents locally, so there is nothing to deploy.";
|
|
345
|
+
readonly shareEmpty: "Nothing has been shared yet.";
|
|
345
346
|
readonly shareGroupReceived: "Inbound";
|
|
346
347
|
readonly shareGroupGiven: "Outbound";
|
|
347
348
|
readonly shareColRelation: "Sharing";
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which documents belong under "Owned by me".
|
|
3
|
+
*
|
|
4
|
+
* Two rules, and the second is the one users asked for explicitly: a document in the
|
|
5
|
+
* caller's own personal folder is theirs, and a document the caller can WRITE is also
|
|
6
|
+
* theirs to manage -- an administrator who maintains `global/` should not have to open
|
|
7
|
+
* the tree to find those files, because the Home tab is where they look first.
|
|
8
|
+
*
|
|
9
|
+
* Write access is not derivable from the tree, so the caller passes in what it knows.
|
|
10
|
+
* The important part is the three-valued answer: "yes", "no" and "not known" are all
|
|
11
|
+
* different, and an unknown permission must not be silently treated as either.
|
|
12
|
+
*
|
|
13
|
+
* @module @sparkelf/dsh-knowledge-base/client
|
|
14
|
+
*/
|
|
15
|
+
/** What the caller knows about one path's manageability. */
|
|
16
|
+
export type Manageability =
|
|
17
|
+
/** The caller may write or manage it. */
|
|
18
|
+
'writable'
|
|
19
|
+
/** The caller may read it but not write it. */
|
|
20
|
+
| 'read-only'
|
|
21
|
+
/** No answer was available: not configured, refused, or not looked up. */
|
|
22
|
+
| 'unknown';
|
|
23
|
+
/** What a row's membership answer is. */
|
|
24
|
+
export type MineVerdict =
|
|
25
|
+
/** Belongs under "Owned by me". */
|
|
26
|
+
'mine'
|
|
27
|
+
/** Does not belong. */
|
|
28
|
+
| 'not-mine'
|
|
29
|
+
/** Cannot be decided; the caller must mark the row rather than drop or claim it. */
|
|
30
|
+
| 'undetermined';
|
|
31
|
+
/**
|
|
32
|
+
* The bucket a path sits in, by its first segment.
|
|
33
|
+
* @param relPath - path relative to the knowledge root.
|
|
34
|
+
* @returns The bucket name, or an empty string when the path is empty.
|
|
35
|
+
*/
|
|
36
|
+
export declare function bucketOfPath(relPath: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* Whether a path sits inside the caller's own personal folder.
|
|
39
|
+
*
|
|
40
|
+
* `personal/<callerId>/...` and nothing else: a sibling's folder is not the caller's,
|
|
41
|
+
* and the caller's bare `personal/` level is a container rather than their documents.
|
|
42
|
+
* @param relPath - path relative to the knowledge root.
|
|
43
|
+
* @param callerId - the caller's own id, when known.
|
|
44
|
+
* @returns True when the path is under the caller's own folder.
|
|
45
|
+
*/
|
|
46
|
+
export declare function isInOwnPersonalFolder(relPath: string, callerId: string | undefined): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Decide whether one path belongs under "Owned by me".
|
|
49
|
+
*
|
|
50
|
+
* The caller's own personal folder is unconditional: it is theirs by construction, and
|
|
51
|
+
* no permission lookup can make it not theirs. Every other path depends on write access,
|
|
52
|
+
* which is why an unknown answer is NOT treated as permission -- showing a document as
|
|
53
|
+
* "mine" when the caller cannot write it would be a claim the deployment cannot back.
|
|
54
|
+
*
|
|
55
|
+
* An undetermined row is neither dropped nor claimed: the caller renders it with a mark,
|
|
56
|
+
* which is the existing degradation for a permission answer that could not be read.
|
|
57
|
+
* @param relPath - path relative to the knowledge root.
|
|
58
|
+
* @param callerId - the caller's own id, when known.
|
|
59
|
+
* @param manageability - what is known about write access for this path.
|
|
60
|
+
* @returns Whether the row is mine, not mine, or undecidable.
|
|
61
|
+
*/
|
|
62
|
+
export declare function mineVerdict(relPath: string, callerId: string | undefined, manageability: Manageability): MineVerdict;
|
|
63
|
+
/**
|
|
64
|
+
* The rows under "Owned by me", given what is known about each.
|
|
65
|
+
*
|
|
66
|
+
* Undetermined rows are included and reported separately, because dropping them is the
|
|
67
|
+
* silent-loss failure the user reported: their files existed and simply did not appear.
|
|
68
|
+
* The caller shows them with a mark rather than hiding them.
|
|
69
|
+
* @param rows - every candidate row, in display order.
|
|
70
|
+
* @param callerId - the caller's own id, when known.
|
|
71
|
+
* @param manageabilityOf - per-path write knowledge.
|
|
72
|
+
* @returns The rows to show and the paths whose answer was undetermined.
|
|
73
|
+
*/
|
|
74
|
+
export declare function selectOwnedRows<T extends {
|
|
75
|
+
relPath: string;
|
|
76
|
+
}>(rows: readonly T[], callerId: string | undefined, manageabilityOf: (relPath: string) => Manageability): {
|
|
77
|
+
rows: T[];
|
|
78
|
+
undetermined: string[];
|
|
79
|
+
};
|
|
@@ -24,14 +24,21 @@ export interface RoleSummary {
|
|
|
24
24
|
builtIn: boolean;
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
|
-
* Collapse raw action strings
|
|
27
|
+
* Collapse raw action strings the way the rest of the page does.
|
|
28
28
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
29
|
+
* This used to carry its own word list, inherited from the create/edit form
|
|
30
|
+
* (`read`/`create`/`update`/`delete`). DataOps stores `read`/`write`/`manage`, so
|
|
31
|
+
* `write` and `manage` matched nothing and were dropped: the role BADGES above the
|
|
32
|
+
* table showed 「只读」 while the table below them — already fixed — showed
|
|
33
|
+
* 读/写/管理. One page, two conclusions, and the reader has no way to tell which is
|
|
34
|
+
* true.
|
|
35
|
+
*
|
|
36
|
+
* It now delegates to {@link resolveActions}, which is the single vocabulary and the
|
|
37
|
+
* single union rule for this package. Do not reintroduce a local list here: a second
|
|
38
|
+
* copy of "what the words mean" is exactly the defect this line removes.
|
|
32
39
|
*
|
|
33
40
|
* @param actions - raw action strings.
|
|
34
|
-
* @returns
|
|
41
|
+
* @returns The unioned actions in product order.
|
|
35
42
|
*/
|
|
36
43
|
export declare function summarizeRoleActions(actions: readonly string[]): string[];
|
|
37
44
|
/**
|
|
@@ -30,7 +30,9 @@ export interface ShareGrant {
|
|
|
30
30
|
export type PrincipalNameOf = (kind: ShareGrant['principalType'], id: string) => string | undefined;
|
|
31
31
|
/** Which group one grant belongs to. */
|
|
32
32
|
export type ShareDirection = 'received' | 'given';
|
|
33
|
-
/**
|
|
33
|
+
/** Which direction a row states. */
|
|
34
|
+
export type ShareRowDirection = 'received' | 'given';
|
|
35
|
+
/** One row of the share table. */
|
|
34
36
|
export interface ShareRow {
|
|
35
37
|
/** Stable row id, taken from the grant. */
|
|
36
38
|
id: string;
|
|
@@ -46,6 +48,14 @@ export interface ShareRow {
|
|
|
46
48
|
audience: string;
|
|
47
49
|
/** The permission the grant confers. */
|
|
48
50
|
action: string;
|
|
51
|
+
/**
|
|
52
|
+
* Which way this share points.
|
|
53
|
+
*
|
|
54
|
+
* Carried on the ROW rather than inferred from which table drew it: the whole point
|
|
55
|
+
* of merging the two blocks into one table is that the direction has to be readable
|
|
56
|
+
* per row, from the relation column.
|
|
57
|
+
*/
|
|
58
|
+
direction: ShareRowDirection;
|
|
49
59
|
}
|
|
50
60
|
/**
|
|
51
61
|
* Whether a grant names the caller directly.
|
|
@@ -79,3 +89,31 @@ export declare function splitShareRelations(grants: readonly ShareGrant[], calle
|
|
|
79
89
|
received: ShareRow[];
|
|
80
90
|
given: ShareRow[];
|
|
81
91
|
};
|
|
92
|
+
/**
|
|
93
|
+
* Every share row in the order one merged table shows them.
|
|
94
|
+
*
|
|
95
|
+
* Inbound first: "what has been shared with me" is the question this tab answers most
|
|
96
|
+
* often, and within each direction the order the grants arrived in is preserved so the
|
|
97
|
+
* table does not reshuffle between reads.
|
|
98
|
+
*
|
|
99
|
+
* A single list rather than two is what lets the tab be one table with one pager; the
|
|
100
|
+
* direction travels on each row so the relation column can state it per row.
|
|
101
|
+
* @param split - the two groups produced by {@link splitShareRelations}.
|
|
102
|
+
* @returns One list, inbound rows before outbound ones.
|
|
103
|
+
*/
|
|
104
|
+
export declare function mergeShareRows(split: {
|
|
105
|
+
received: readonly ShareRow[];
|
|
106
|
+
given: readonly ShareRow[];
|
|
107
|
+
}): ShareRow[];
|
|
108
|
+
/**
|
|
109
|
+
* The text one row's relation column shows.
|
|
110
|
+
*
|
|
111
|
+
* `receivedTemplate` is a fixed phrase: the grant data has no grantor, so naming one
|
|
112
|
+
* would be a fabrication. `givenTemplate` interpolates the audience, which IS in the
|
|
113
|
+
* data (it is the grant's principal).
|
|
114
|
+
* @param row - the row to describe.
|
|
115
|
+
* @param receivedTemplate - the fixed phrase for an inbound share.
|
|
116
|
+
* @param givenTemplate - the outbound template containing `{audience}`.
|
|
117
|
+
* @returns The relation text.
|
|
118
|
+
*/
|
|
119
|
+
export declare function shareRelationText(row: ShareRow, receivedTemplate: string, givenTemplate: string): string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sparkelf/dsh-knowledge-base",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "DataOps-backed knowledge base for DeepSeek Harness: a left-sidebar destination, Settings configuration, and index tooling over a mounted NAS view.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|