dna-sdk 0.10.0 → 0.12.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/bootstrap.js +6 -0
- package/dist/extensions/cloud/kinds/tenant-plan.kind.yaml +105 -0
- package/dist/extensions/cloud/kinds/tier.kind.yaml +135 -0
- package/dist/extensions/cloud.d.ts +31 -0
- package/dist/extensions/cloud.js +39 -0
- package/dist/extensions/guardrails.js +4 -0
- package/dist/extensions/helix.js +19 -6
- package/dist/extensions/intel/kinds/insight.kind.yaml +148 -0
- package/dist/extensions/intel/kinds/intel-source.kind.yaml +117 -0
- package/dist/extensions/intel.d.ts +30 -0
- package/dist/extensions/intel.js +38 -0
- package/dist/extensions/portfolio/kinds/membership.kind.yaml +114 -0
- package/dist/extensions/portfolio/kinds/organization.kind.yaml +99 -0
- package/dist/extensions/portfolio/kinds/project.kind.yaml +124 -0
- package/dist/extensions/portfolio/kinds/repo.kind.yaml +99 -0
- package/dist/extensions/portfolio/kinds/role.kind.yaml +96 -0
- package/dist/extensions/portfolio.d.ts +45 -0
- package/dist/extensions/portfolio.js +53 -0
- package/dist/extensions/sdlc/kinds/lesson-learned.kind.yaml +0 -1
- package/dist/index.d.ts +1 -0
- package/dist/kernel/composition-resolver.js +17 -1
- package/dist/kernel/index.d.ts +50 -0
- package/dist/kernel/index.js +98 -0
- package/dist/kernel/instance.d.ts +8 -0
- package/dist/kernel/instance.js +9 -0
- package/dist/kernel/kind_base.d.ts +10 -0
- package/dist/kernel/kind_base.js +36 -18
- package/dist/kernel/meta.d.ts +1 -0
- package/dist/kernel/meta.js +11 -1
- package/dist/kernel/models.d.ts +23 -23
- package/dist/kernel/models.js +8 -2
- package/dist/kernel/prompt-builder.d.ts +64 -0
- package/dist/kernel/prompt-builder.js +208 -3
- package/dist/kernel/write-pipeline.d.ts +6 -0
- package/dist/kernel/write-pipeline.js +7 -0
- package/package.json +1 -1
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IntelExtension — DNA intelligence-layer data foundation.
|
|
3
|
+
*
|
|
4
|
+
* 1:1 parity with Python `dna.extensions.intel`.
|
|
5
|
+
*
|
|
6
|
+
* Registers 2 record Kinds, from descriptors (F3 — record Kinds are data, not
|
|
7
|
+
* classes):
|
|
8
|
+
*
|
|
9
|
+
* - IntelSource (`intel-source`) — a watched portfolio source (the
|
|
10
|
+
* "Direction" stage: what the DNA observes). One doc per source (a repo, a
|
|
11
|
+
* scope, or an external URL) carrying its research cadence, actionability
|
|
12
|
+
* threshold, Priority Intelligence Requirements (PIRs) and mute state.
|
|
13
|
+
* TENANTED — a source is the tenant's OWN watchlist (per-tenant user
|
|
14
|
+
* data), NOT a shared `_lib` default. It is deliberately NOT inheritable
|
|
15
|
+
* (never in DEFAULT_INHERITABLE_KINDS_V1), so TENANTED is correct.
|
|
16
|
+
* - Insight (`intel-insight`, kind name `IntelInsight`) — the
|
|
17
|
+
* dissemination unit: a ranked, actionable insight that the
|
|
18
|
+
* ranker/digest/dedup/feedback stages reference. TENANTED for the same
|
|
19
|
+
* reason (per-tenant generated data). Embeddable (`embed: [title, fact]`)
|
|
20
|
+
* so a later dedup story can do semantic recall.
|
|
21
|
+
*
|
|
22
|
+
* This is the foundation ONLY — the research/ranker/digest/feedback stages
|
|
23
|
+
* land in later stories; here we ship just the two data Kinds.
|
|
24
|
+
*/
|
|
25
|
+
import { loadDescriptors } from "../kernel/descriptor-loader.js";
|
|
26
|
+
export class IntelExtension {
|
|
27
|
+
name = "intel";
|
|
28
|
+
version = "1.0.0";
|
|
29
|
+
register(kernel) {
|
|
30
|
+
// F3: both Kinds ship as kinds/*.kind.yaml package data (byte-identical
|
|
31
|
+
// Py↔TS mirror), registered through the SAME funnel as per-scope
|
|
32
|
+
// KindDefinitions (plane lint + digest idempotency + builtin conflict
|
|
33
|
+
// marker).
|
|
34
|
+
for (const raw of loadDescriptors(import.meta.url, "intel/kinds")) {
|
|
35
|
+
kernel.kindFromDescriptor(raw);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Membership — the RBAC join (record plane): a user's role at an org- or
|
|
2
|
+
# project-scope. Named `Membership` (NOT the bare tenant Kind `TenantMembership`,
|
|
3
|
+
# alias tenant-membership, which links a user to a platform-level Tenant) — this
|
|
4
|
+
# one is the portfolio access grant a user holds within a tenant's own
|
|
5
|
+
# Organization / Project graph. The role names mirror the standard ladder
|
|
6
|
+
# (owner / admin / member / guest, highest-role-wins, org-owner superuser); a
|
|
7
|
+
# custom-role follow-up would relax this enum to a free reference into the Role
|
|
8
|
+
# Kind (see role.kind.yaml — the ladder is data so it can be extended).
|
|
9
|
+
#
|
|
10
|
+
# TENANTED — a membership is per-tenant access data, NOT a shared `_lib` default.
|
|
11
|
+
# Deliberately NOT inheritable (never in DEFAULT_INHERITABLE_KINDS_V1); TENANTED
|
|
12
|
+
# is correct.
|
|
13
|
+
#
|
|
14
|
+
# PARITY-CRITICAL package data: the byte-identical mirror lives at
|
|
15
|
+
# packages/sdk-{py,ts}/{dna/extensions,src/extensions}/portfolio/kinds/
|
|
16
|
+
# membership.kind.yaml (tests/test_descriptor_hash_parity.py enforces).
|
|
17
|
+
apiVersion: github.com/ruinosus/dna/core/v1
|
|
18
|
+
kind: KindDefinition
|
|
19
|
+
metadata:
|
|
20
|
+
name: membership
|
|
21
|
+
spec:
|
|
22
|
+
target_api_version: github.com/ruinosus/dna/portfolio/v1
|
|
23
|
+
target_kind: Membership
|
|
24
|
+
alias: portfolio-membership
|
|
25
|
+
origin: github.com/ruinosus/dna/portfolio
|
|
26
|
+
tenant_scope: tenanted
|
|
27
|
+
plane: record
|
|
28
|
+
prompt_target: false
|
|
29
|
+
flatten_in_context: false
|
|
30
|
+
prompt_target_priority: 0
|
|
31
|
+
storage:
|
|
32
|
+
type: yaml
|
|
33
|
+
container: memberships
|
|
34
|
+
schema:
|
|
35
|
+
type: object
|
|
36
|
+
additionalProperties: false
|
|
37
|
+
required:
|
|
38
|
+
- user
|
|
39
|
+
- scope_type
|
|
40
|
+
- scope_ref
|
|
41
|
+
- role
|
|
42
|
+
properties:
|
|
43
|
+
user:
|
|
44
|
+
type: string
|
|
45
|
+
description: The member's identity — an email or stable user id.
|
|
46
|
+
scope_type:
|
|
47
|
+
type: string
|
|
48
|
+
enum:
|
|
49
|
+
- org
|
|
50
|
+
- project
|
|
51
|
+
description: What the grant is scoped to — an Organization (org) or a single
|
|
52
|
+
Project (project).
|
|
53
|
+
scope_ref:
|
|
54
|
+
type: string
|
|
55
|
+
description: The Organization or Project name this grant applies to (paired
|
|
56
|
+
with scope_type).
|
|
57
|
+
role:
|
|
58
|
+
type: string
|
|
59
|
+
enum:
|
|
60
|
+
- owner
|
|
61
|
+
- admin
|
|
62
|
+
- member
|
|
63
|
+
- guest
|
|
64
|
+
description: The role granted at this scope — the standard ladder
|
|
65
|
+
(owner > admin > member > guest). Resolution is highest-role-wins across
|
|
66
|
+
a user's memberships, with the org owner a superuser.
|
|
67
|
+
status:
|
|
68
|
+
type: string
|
|
69
|
+
enum:
|
|
70
|
+
- invited
|
|
71
|
+
- active
|
|
72
|
+
default: invited
|
|
73
|
+
description: Invitation lifecycle — invited (pending acceptance) or active.
|
|
74
|
+
invited_at:
|
|
75
|
+
type:
|
|
76
|
+
- string
|
|
77
|
+
- 'null'
|
|
78
|
+
description: ISO-8601 timestamp of the invite, stamped by the writer (not
|
|
79
|
+
defaulted here).
|
|
80
|
+
describe: '{user} → {scope_ref} ({role})'
|
|
81
|
+
summary:
|
|
82
|
+
user: ''
|
|
83
|
+
scope_type: ''
|
|
84
|
+
scope_ref: ''
|
|
85
|
+
role: ''
|
|
86
|
+
status: invited
|
|
87
|
+
ui:
|
|
88
|
+
mode: govern
|
|
89
|
+
label:
|
|
90
|
+
en: Memberships
|
|
91
|
+
pt-BR: Membros
|
|
92
|
+
icon: 👤
|
|
93
|
+
description:
|
|
94
|
+
en: RBAC grants — a user's role at an org or project scope (highest-role-wins).
|
|
95
|
+
pt-BR: Concessões RBAC — o papel de um usuário num escopo de org ou projeto
|
|
96
|
+
(maior-papel-vence).
|
|
97
|
+
routes:
|
|
98
|
+
list: docs/Membership
|
|
99
|
+
detail: docs/Membership/:name
|
|
100
|
+
permissions:
|
|
101
|
+
list: any
|
|
102
|
+
detail: any
|
|
103
|
+
in_sidebar: true
|
|
104
|
+
display_order: 61
|
|
105
|
+
ascii_icon: 👤
|
|
106
|
+
display_label: Memberships
|
|
107
|
+
docs: A Membership is the RBAC join — a user's role at an org- or project-scope
|
|
108
|
+
within a tenant's portfolio. It carries the user (email / id), the scope_type
|
|
109
|
+
(org / project) and scope_ref it applies to, the role from the standard ladder
|
|
110
|
+
(owner > admin > member > guest, highest-role-wins, org-owner superuser), and
|
|
111
|
+
an invitation status (invited / active), as per-tenant declarative data. It is
|
|
112
|
+
distinct from the platform-level TenantMembership (which links a user to a
|
|
113
|
+
provisioning Tenant); this grants access inside the tenant's own Organization /
|
|
114
|
+
Project graph.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Organization — a tenant's org profile (record plane; the top-level container).
|
|
2
|
+
# One doc per tenant: the human-facing identity of the organization whose
|
|
3
|
+
# portfolio of Projects the DNA Cloud console aggregates. Named `Organization`
|
|
4
|
+
# (the enterprise-familiar top-level term — GitHub/Azure DevOps) so procurement
|
|
5
|
+
# recognizes it; it is the tenant's OWN profile, distinct from the platform-level
|
|
6
|
+
# `Tenant` provisioning identity Kind (GLOBAL, `_lib`) — this one is the editable
|
|
7
|
+
# org profile that lives inside the tenant's own portfolio.
|
|
8
|
+
#
|
|
9
|
+
# TENANTED — the org profile is per-tenant user data (one Organization per
|
|
10
|
+
# tenant), NOT a shared `_lib` default consumed by other scopes. It is
|
|
11
|
+
# deliberately NOT inheritable (never in DEFAULT_INHERITABLE_KINDS_V1); TENANTED
|
|
12
|
+
# is the correct tenancy for per-tenant data without a platform default.
|
|
13
|
+
#
|
|
14
|
+
# PARITY-CRITICAL package data: the byte-identical mirror lives at
|
|
15
|
+
# packages/sdk-{py,ts}/{dna/extensions,src/extensions}/portfolio/kinds/
|
|
16
|
+
# organization.kind.yaml (tests/test_descriptor_hash_parity.py enforces).
|
|
17
|
+
apiVersion: github.com/ruinosus/dna/core/v1
|
|
18
|
+
kind: KindDefinition
|
|
19
|
+
metadata:
|
|
20
|
+
name: organization
|
|
21
|
+
spec:
|
|
22
|
+
target_api_version: github.com/ruinosus/dna/portfolio/v1
|
|
23
|
+
target_kind: Organization
|
|
24
|
+
alias: portfolio-org
|
|
25
|
+
origin: github.com/ruinosus/dna/portfolio
|
|
26
|
+
tenant_scope: tenanted
|
|
27
|
+
plane: record
|
|
28
|
+
prompt_target: false
|
|
29
|
+
flatten_in_context: false
|
|
30
|
+
prompt_target_priority: 0
|
|
31
|
+
storage:
|
|
32
|
+
type: yaml
|
|
33
|
+
container: organizations
|
|
34
|
+
schema:
|
|
35
|
+
type: object
|
|
36
|
+
additionalProperties: false
|
|
37
|
+
required:
|
|
38
|
+
- name
|
|
39
|
+
- slug
|
|
40
|
+
properties:
|
|
41
|
+
name:
|
|
42
|
+
type: string
|
|
43
|
+
description: The organization's canonical name. The doc name SHOULD equal
|
|
44
|
+
this.
|
|
45
|
+
slug:
|
|
46
|
+
type: string
|
|
47
|
+
description: URL-safe identity for the org, e.g. acme-corp. Used in routes
|
|
48
|
+
and as a stable handle for the tenant's portfolio.
|
|
49
|
+
display_name:
|
|
50
|
+
type:
|
|
51
|
+
- string
|
|
52
|
+
- 'null'
|
|
53
|
+
description: Human-facing name shown in the console. Falls back to name.
|
|
54
|
+
plan_ref:
|
|
55
|
+
type:
|
|
56
|
+
- string
|
|
57
|
+
- 'null'
|
|
58
|
+
description: The DNA Cloud Tier / TenantPlan this org is on (a Tier tier_id
|
|
59
|
+
or TenantPlan name). Null falls back to Free. The billing→enforcement
|
|
60
|
+
bridge reads it; the OSS SDK only stores it.
|
|
61
|
+
created_at:
|
|
62
|
+
type:
|
|
63
|
+
- string
|
|
64
|
+
- 'null'
|
|
65
|
+
description: ISO-8601 timestamp, stamped by the writer (not defaulted here).
|
|
66
|
+
describe: '{name}'
|
|
67
|
+
summary:
|
|
68
|
+
name: ''
|
|
69
|
+
slug: ''
|
|
70
|
+
plan_ref: null
|
|
71
|
+
ui:
|
|
72
|
+
mode: govern
|
|
73
|
+
label:
|
|
74
|
+
en: Organizations
|
|
75
|
+
pt-BR: Organizações
|
|
76
|
+
icon: 🏛️
|
|
77
|
+
description:
|
|
78
|
+
en: The tenant's org profile (the top-level container the portfolio console
|
|
79
|
+
aggregates).
|
|
80
|
+
pt-BR: O perfil da organização do tenant (o container de topo que o console
|
|
81
|
+
de portfólio agrega).
|
|
82
|
+
routes:
|
|
83
|
+
list: docs/Organization
|
|
84
|
+
detail: docs/Organization/:name
|
|
85
|
+
permissions:
|
|
86
|
+
list: any
|
|
87
|
+
detail: any
|
|
88
|
+
in_sidebar: true
|
|
89
|
+
display_order: 58
|
|
90
|
+
ascii_icon: 🏛️
|
|
91
|
+
display_label: Organizations
|
|
92
|
+
docs: An Organization is the tenant's own org profile — the enterprise-familiar
|
|
93
|
+
top-level container (as in GitHub / Azure DevOps) whose portfolio of Projects
|
|
94
|
+
the DNA Cloud console aggregates. It carries the org name, a URL-safe slug, an
|
|
95
|
+
optional display name, and a plan_ref to the DNA Cloud Tier / TenantPlan the
|
|
96
|
+
org is on, as per-tenant declarative data. One Organization per tenant; it is
|
|
97
|
+
distinct from the platform-level Tenant provisioning identity Kind (the
|
|
98
|
+
editable org profile inside the tenant's own portfolio, not the GLOBAL
|
|
99
|
+
identity row).
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# Project — the multi-repo development-space container (record plane; the KEY
|
|
2
|
+
# Kind of the portfolio model). Formalizes the marriage of three primitives the
|
|
3
|
+
# DNA already has: (a) a SDLC board scope (convention <slug>-development), (b) one
|
|
4
|
+
# or more IntelSources (the intelligence layer observes them), and (c) scoped
|
|
5
|
+
# memory. This is the Azure DevOps-style container: a Project OWNS its board +
|
|
6
|
+
# intel + memory and is the permission boundary; repos are ATTACHED BY REFERENCE.
|
|
7
|
+
#
|
|
8
|
+
# N—N Repo↔Project (decided with the owner): the edge lives HERE, as `repo_refs`
|
|
9
|
+
# (a list of Repo names). A repo can belong to MULTIPLE Projects without being
|
|
10
|
+
# duplicated; the Repo Kind deliberately carries NO project back-ref (single
|
|
11
|
+
# source of truth for the edge — the Project side). Modelling the reverse as a
|
|
12
|
+
# join Kind was considered and rejected as premature: a list of names on the
|
|
13
|
+
# Project is the smallest thing that expresses N—N here.
|
|
14
|
+
#
|
|
15
|
+
# TENANTED — a Project is the tenant's own development space (per-tenant data),
|
|
16
|
+
# NOT a shared `_lib` default. Deliberately NOT inheritable (never in
|
|
17
|
+
# DEFAULT_INHERITABLE_KINDS_V1); TENANTED is correct.
|
|
18
|
+
#
|
|
19
|
+
# PARITY-CRITICAL package data: the byte-identical mirror lives at
|
|
20
|
+
# packages/sdk-{py,ts}/{dna/extensions,src/extensions}/portfolio/kinds/
|
|
21
|
+
# project.kind.yaml (tests/test_descriptor_hash_parity.py enforces).
|
|
22
|
+
apiVersion: github.com/ruinosus/dna/core/v1
|
|
23
|
+
kind: KindDefinition
|
|
24
|
+
metadata:
|
|
25
|
+
name: project
|
|
26
|
+
spec:
|
|
27
|
+
target_api_version: github.com/ruinosus/dna/portfolio/v1
|
|
28
|
+
target_kind: Project
|
|
29
|
+
alias: portfolio-project
|
|
30
|
+
origin: github.com/ruinosus/dna/portfolio
|
|
31
|
+
tenant_scope: tenanted
|
|
32
|
+
plane: record
|
|
33
|
+
prompt_target: false
|
|
34
|
+
flatten_in_context: false
|
|
35
|
+
prompt_target_priority: 0
|
|
36
|
+
storage:
|
|
37
|
+
type: yaml
|
|
38
|
+
container: projects
|
|
39
|
+
schema:
|
|
40
|
+
type: object
|
|
41
|
+
additionalProperties: false
|
|
42
|
+
required:
|
|
43
|
+
- name
|
|
44
|
+
- slug
|
|
45
|
+
properties:
|
|
46
|
+
name:
|
|
47
|
+
type: string
|
|
48
|
+
description: The project's canonical name. The doc name SHOULD equal this.
|
|
49
|
+
slug:
|
|
50
|
+
type: string
|
|
51
|
+
description: URL-safe identity for the project, e.g. copiloto-medico. Used
|
|
52
|
+
in routes and to derive the board_scope by convention.
|
|
53
|
+
org_ref:
|
|
54
|
+
type:
|
|
55
|
+
- string
|
|
56
|
+
- 'null'
|
|
57
|
+
description: The Organization (name) this project belongs to. Null while
|
|
58
|
+
unassigned.
|
|
59
|
+
repo_refs:
|
|
60
|
+
type: array
|
|
61
|
+
items:
|
|
62
|
+
type: string
|
|
63
|
+
description: Repo names attached to this project (the N—N edge — a repo may
|
|
64
|
+
appear on multiple projects). The edge lives on the Project side only.
|
|
65
|
+
board_scope:
|
|
66
|
+
type:
|
|
67
|
+
- string
|
|
68
|
+
- 'null'
|
|
69
|
+
description: The SDLC scope this project owns (convention <slug>-development).
|
|
70
|
+
Where its Stories / Issues / Epics live.
|
|
71
|
+
intel_source_refs:
|
|
72
|
+
type: array
|
|
73
|
+
items:
|
|
74
|
+
type: string
|
|
75
|
+
description: IntelSource names the intelligence layer observes for this
|
|
76
|
+
project (the sources feeding its insight stream).
|
|
77
|
+
visibility:
|
|
78
|
+
type: string
|
|
79
|
+
enum:
|
|
80
|
+
- private
|
|
81
|
+
- shared
|
|
82
|
+
default: private
|
|
83
|
+
description: Who can see the project — private (org-internal) or shared
|
|
84
|
+
(visible across the portfolio).
|
|
85
|
+
created_at:
|
|
86
|
+
type:
|
|
87
|
+
- string
|
|
88
|
+
- 'null'
|
|
89
|
+
description: ISO-8601 timestamp, stamped by the writer (not defaulted here).
|
|
90
|
+
describe: '{name}'
|
|
91
|
+
summary:
|
|
92
|
+
name: ''
|
|
93
|
+
slug: ''
|
|
94
|
+
org_ref: null
|
|
95
|
+
visibility: private
|
|
96
|
+
ui:
|
|
97
|
+
mode: govern
|
|
98
|
+
label:
|
|
99
|
+
en: Projects
|
|
100
|
+
pt-BR: Projetos
|
|
101
|
+
icon: 📁
|
|
102
|
+
description:
|
|
103
|
+
en: Multi-repo development-space containers (board + intel + memory; repos
|
|
104
|
+
attached by reference).
|
|
105
|
+
pt-BR: Containers de espaço-de-desenvolvimento multi-repo (board + inteligência
|
|
106
|
+
+ memória; repos anexados por referência).
|
|
107
|
+
routes:
|
|
108
|
+
list: docs/Project
|
|
109
|
+
detail: docs/Project/:name
|
|
110
|
+
permissions:
|
|
111
|
+
list: any
|
|
112
|
+
detail: any
|
|
113
|
+
in_sidebar: true
|
|
114
|
+
display_order: 59
|
|
115
|
+
ascii_icon: 📁
|
|
116
|
+
display_label: Projects
|
|
117
|
+
docs: A Project is the multi-repo development-space container — the key Kind of
|
|
118
|
+
the portfolio model. It owns a SDLC board scope (convention <slug>-development),
|
|
119
|
+
one or more IntelSources the intelligence layer observes, and scoped memory,
|
|
120
|
+
and it is the permission boundary. Repos are attached BY REFERENCE via repo_refs
|
|
121
|
+
(an N—N edge kept on the Project side — a repo can belong to many projects
|
|
122
|
+
without duplication; Repo carries no project back-ref). A Project has a
|
|
123
|
+
visibility (private / shared) and an org_ref to its Organization, as per-tenant
|
|
124
|
+
declarative data.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Repo — a code repository the portfolio references (record plane). A source of
|
|
2
|
+
# code attached to N Projects via Project.repo_refs (the N—N edge lives on the
|
|
3
|
+
# Project side). A Repo deliberately carries NO project back-ref: the edge has a
|
|
4
|
+
# single source of truth (the Project), so a repo shared across projects is never
|
|
5
|
+
# duplicated and never carries a stale reverse list. Resolving "which projects
|
|
6
|
+
# reference this repo" is a query over Projects, not a stored field.
|
|
7
|
+
#
|
|
8
|
+
# TENANTED — a repo is part of the tenant's own portfolio (per-tenant data), NOT
|
|
9
|
+
# a shared `_lib` default. Deliberately NOT inheritable (never in
|
|
10
|
+
# DEFAULT_INHERITABLE_KINDS_V1); TENANTED is correct.
|
|
11
|
+
#
|
|
12
|
+
# PARITY-CRITICAL package data: the byte-identical mirror lives at
|
|
13
|
+
# packages/sdk-{py,ts}/{dna/extensions,src/extensions}/portfolio/kinds/
|
|
14
|
+
# repo.kind.yaml (tests/test_descriptor_hash_parity.py enforces).
|
|
15
|
+
apiVersion: github.com/ruinosus/dna/core/v1
|
|
16
|
+
kind: KindDefinition
|
|
17
|
+
metadata:
|
|
18
|
+
name: repo
|
|
19
|
+
spec:
|
|
20
|
+
target_api_version: github.com/ruinosus/dna/portfolio/v1
|
|
21
|
+
target_kind: Repo
|
|
22
|
+
alias: portfolio-repo
|
|
23
|
+
origin: github.com/ruinosus/dna/portfolio
|
|
24
|
+
tenant_scope: tenanted
|
|
25
|
+
plane: record
|
|
26
|
+
prompt_target: false
|
|
27
|
+
flatten_in_context: false
|
|
28
|
+
prompt_target_priority: 0
|
|
29
|
+
storage:
|
|
30
|
+
type: yaml
|
|
31
|
+
container: repos
|
|
32
|
+
schema:
|
|
33
|
+
type: object
|
|
34
|
+
additionalProperties: false
|
|
35
|
+
required:
|
|
36
|
+
- name
|
|
37
|
+
properties:
|
|
38
|
+
name:
|
|
39
|
+
type: string
|
|
40
|
+
description: The repo name, e.g. copiloto-medico. The doc name SHOULD equal
|
|
41
|
+
this; Project.repo_refs point at it.
|
|
42
|
+
url:
|
|
43
|
+
type:
|
|
44
|
+
- string
|
|
45
|
+
- 'null'
|
|
46
|
+
description: Clone / browse URL of the repository. Null when the name alone
|
|
47
|
+
identifies it.
|
|
48
|
+
provider:
|
|
49
|
+
type: string
|
|
50
|
+
enum:
|
|
51
|
+
- github
|
|
52
|
+
- gitlab
|
|
53
|
+
- azure-devops
|
|
54
|
+
- other
|
|
55
|
+
default: github
|
|
56
|
+
description: Where the repo is hosted — github, gitlab, azure-devops, or
|
|
57
|
+
other.
|
|
58
|
+
default_branch:
|
|
59
|
+
type:
|
|
60
|
+
- string
|
|
61
|
+
- 'null'
|
|
62
|
+
description: The repo's default branch, e.g. main. Null when unknown.
|
|
63
|
+
created_at:
|
|
64
|
+
type:
|
|
65
|
+
- string
|
|
66
|
+
- 'null'
|
|
67
|
+
description: ISO-8601 timestamp, stamped by the writer (not defaulted here).
|
|
68
|
+
describe: '{name}'
|
|
69
|
+
summary:
|
|
70
|
+
name: ''
|
|
71
|
+
provider: ''
|
|
72
|
+
default_branch: null
|
|
73
|
+
ui:
|
|
74
|
+
mode: govern
|
|
75
|
+
label:
|
|
76
|
+
en: Repos
|
|
77
|
+
pt-BR: Repositórios
|
|
78
|
+
icon: 📦
|
|
79
|
+
description:
|
|
80
|
+
en: Code repositories the portfolio references (attached to projects by
|
|
81
|
+
reference, N—N).
|
|
82
|
+
pt-BR: Repositórios de código que o portfólio referencia (anexados a projetos
|
|
83
|
+
por referência, N—N).
|
|
84
|
+
routes:
|
|
85
|
+
list: docs/Repo
|
|
86
|
+
detail: docs/Repo/:name
|
|
87
|
+
permissions:
|
|
88
|
+
list: any
|
|
89
|
+
detail: any
|
|
90
|
+
in_sidebar: true
|
|
91
|
+
display_order: 60
|
|
92
|
+
ascii_icon: 📦
|
|
93
|
+
display_label: Repos
|
|
94
|
+
docs: A Repo is a code repository the portfolio references — its name, url,
|
|
95
|
+
provider (github / gitlab / azure-devops / other) and default_branch, as
|
|
96
|
+
per-tenant declarative data. It is attached to N Projects via Project.repo_refs
|
|
97
|
+
(the N—N edge lives on the Project side); a Repo carries no project back-ref,
|
|
98
|
+
so a repo shared across projects is never duplicated. "Which projects use this
|
|
99
|
+
repo" is a query over Projects, not a stored reverse list.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Role — the RBAC role ladder AS DATA (record plane; the DNA thesis: everything
|
|
2
|
+
# declarative). Instead of a hardcoded enum, each rung of the ladder is a Role
|
|
3
|
+
# doc carrying its rank (higher = more access) and the capabilities it grants, so
|
|
4
|
+
# the ladder is EXTENSIBLE — a tenant can add a custom role between member and
|
|
5
|
+
# admin without a code change. The four standard rungs (owner / admin / member /
|
|
6
|
+
# guest) ship as seed / example docs (examples/dna-cloud/.dna/.../roles/).
|
|
7
|
+
# highest-role-wins compares `rank`; the org owner is a superuser above the ladder.
|
|
8
|
+
#
|
|
9
|
+
# TENANTED — a tenant owns its OWN role set (seeded from the standard ladder, then
|
|
10
|
+
# customizable), NOT a shared `_lib` default. Deliberately NOT inheritable (never
|
|
11
|
+
# in DEFAULT_INHERITABLE_KINDS_V1); TENANTED is correct — this is why the standard
|
|
12
|
+
# rungs ship as per-tenant seed docs rather than a GLOBAL registry.
|
|
13
|
+
#
|
|
14
|
+
# PARITY-CRITICAL package data: the byte-identical mirror lives at
|
|
15
|
+
# packages/sdk-{py,ts}/{dna/extensions,src/extensions}/portfolio/kinds/
|
|
16
|
+
# role.kind.yaml (tests/test_descriptor_hash_parity.py enforces).
|
|
17
|
+
apiVersion: github.com/ruinosus/dna/core/v1
|
|
18
|
+
kind: KindDefinition
|
|
19
|
+
metadata:
|
|
20
|
+
name: role
|
|
21
|
+
spec:
|
|
22
|
+
target_api_version: github.com/ruinosus/dna/portfolio/v1
|
|
23
|
+
target_kind: Role
|
|
24
|
+
alias: portfolio-role
|
|
25
|
+
origin: github.com/ruinosus/dna/portfolio
|
|
26
|
+
tenant_scope: tenanted
|
|
27
|
+
plane: record
|
|
28
|
+
prompt_target: false
|
|
29
|
+
flatten_in_context: false
|
|
30
|
+
prompt_target_priority: 0
|
|
31
|
+
storage:
|
|
32
|
+
type: yaml
|
|
33
|
+
container: roles
|
|
34
|
+
schema:
|
|
35
|
+
type: object
|
|
36
|
+
additionalProperties: false
|
|
37
|
+
required:
|
|
38
|
+
- role_id
|
|
39
|
+
- display_name
|
|
40
|
+
- rank
|
|
41
|
+
properties:
|
|
42
|
+
role_id:
|
|
43
|
+
type: string
|
|
44
|
+
description: Canonical role id, e.g. owner / admin / member / guest. The doc
|
|
45
|
+
name SHOULD equal this; Membership.role references it.
|
|
46
|
+
display_name:
|
|
47
|
+
type: string
|
|
48
|
+
description: Human-facing role name, e.g. Owner, Admin, Member, Guest.
|
|
49
|
+
rank:
|
|
50
|
+
type: integer
|
|
51
|
+
description: Ladder rank — higher = more access. highest-role-wins compares
|
|
52
|
+
this across a user's memberships.
|
|
53
|
+
capabilities:
|
|
54
|
+
type: array
|
|
55
|
+
items:
|
|
56
|
+
type: string
|
|
57
|
+
description: The grants this role unlocks (e.g. project.write, member.invite,
|
|
58
|
+
billing.manage). The permission checker reads them from here.
|
|
59
|
+
can_delete:
|
|
60
|
+
type: boolean
|
|
61
|
+
default: true
|
|
62
|
+
description: False for the built-in ladder rungs that must not be removed
|
|
63
|
+
(e.g. owner); true for custom roles a tenant adds.
|
|
64
|
+
describe: '{display_name} (rank {rank})'
|
|
65
|
+
summary:
|
|
66
|
+
role_id: ''
|
|
67
|
+
display_name: ''
|
|
68
|
+
rank: 0
|
|
69
|
+
can_delete: true
|
|
70
|
+
ui:
|
|
71
|
+
mode: govern
|
|
72
|
+
label:
|
|
73
|
+
en: Roles
|
|
74
|
+
pt-BR: Papéis
|
|
75
|
+
icon: 🎚️
|
|
76
|
+
description:
|
|
77
|
+
en: The RBAC role ladder as data (extensible — add a custom rung without code).
|
|
78
|
+
pt-BR: A escada de papéis RBAC como dado (extensível — adicione um degrau sem
|
|
79
|
+
código).
|
|
80
|
+
routes:
|
|
81
|
+
list: docs/Role
|
|
82
|
+
detail: docs/Role/:name
|
|
83
|
+
permissions:
|
|
84
|
+
list: any
|
|
85
|
+
detail: any
|
|
86
|
+
in_sidebar: true
|
|
87
|
+
display_order: 62
|
|
88
|
+
ascii_icon: 🎚️
|
|
89
|
+
display_label: Roles
|
|
90
|
+
docs: A Role is one rung of the RBAC ladder expressed as data — its role_id,
|
|
91
|
+
display_name, rank (higher = more access), the capabilities it grants, and a
|
|
92
|
+
can_delete flag protecting built-in rungs. Modelling the ladder as data (not a
|
|
93
|
+
hardcoded enum) makes it extensible — a tenant can add a custom role without a
|
|
94
|
+
code change, and highest-role-wins simply compares rank. The four standard
|
|
95
|
+
rungs (owner / admin / member / guest) ship as per-tenant seed docs; the org
|
|
96
|
+
owner is a superuser above the ladder.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PortfolioExtension — DNA Cloud portfolio-console data foundation.
|
|
3
|
+
*
|
|
4
|
+
* 1:1 parity with Python `dna.extensions.portfolio`.
|
|
5
|
+
*
|
|
6
|
+
* Registers 5 record Kinds, from descriptors (F3 — record Kinds are data, not
|
|
7
|
+
* classes). The accepted model (adr-portfolio-project-model): an Organization
|
|
8
|
+
* (the tenant boundary) owns Projects; a Project is a multi-repo CONTAINER that
|
|
9
|
+
* owns its board scope + intel sources + memory; RBAC is the standard ladder.
|
|
10
|
+
*
|
|
11
|
+
* - Organization (`portfolio-org`) — the tenant's org profile, the
|
|
12
|
+
* enterprise-familiar top-level container the console aggregates. One per
|
|
13
|
+
* tenant. Distinct from the platform-level `Tenant` provisioning identity
|
|
14
|
+
* Kind (GLOBAL); this is the editable profile inside the tenant's portfolio.
|
|
15
|
+
* - Project (`portfolio-project`) — the KEY Kind: the multi-repo
|
|
16
|
+
* development-space container that OWNS a board scope (`<slug>-development`),
|
|
17
|
+
* IntelSources and memory, and is the permission boundary. Repos are
|
|
18
|
+
* attached BY REFERENCE via `repo_refs` (the N—N edge lives on the Project
|
|
19
|
+
* side).
|
|
20
|
+
* - Repo (`portfolio-repo`) — a code repository the portfolio references.
|
|
21
|
+
* Attached to N Projects via `Project.repo_refs`; carries NO project
|
|
22
|
+
* back-ref (single source of truth for the N—N edge → no duplication).
|
|
23
|
+
* - Membership (`portfolio-membership`) — the RBAC join: a user's role at an
|
|
24
|
+
* org- or project-scope (standard ladder owner > admin > member > guest,
|
|
25
|
+
* highest-role-wins, org-owner superuser). Distinct from the tenant Kind
|
|
26
|
+
* `TenantMembership` (which links a user to a provisioning Tenant).
|
|
27
|
+
* - Role (`portfolio-role`) — the role ladder AS DATA (the DNA thesis):
|
|
28
|
+
* each rung a doc with `rank` + `capabilities`, so the ladder is extensible
|
|
29
|
+
* (custom roles) rather than a hardcoded enum. The four standard rungs ship
|
|
30
|
+
* as per-tenant seed docs (examples/dna-cloud/.dna/.../roles/).
|
|
31
|
+
*
|
|
32
|
+
* All 5 are TENANTED — per-tenant portfolio data, NOT shared `_lib` defaults,
|
|
33
|
+
* and deliberately NOT inheritable (never in DEFAULT_INHERITABLE_KINDS_V1), so
|
|
34
|
+
* TENANTED is the correct tenancy.
|
|
35
|
+
*
|
|
36
|
+
* This is the data foundation ONLY — the console UI, the resolve_role helper
|
|
37
|
+
* (highest-role-wins + org-owner superuser) and the enterprise SSO/SCIM layer
|
|
38
|
+
* land in later stories; here we ship just the five data Kinds.
|
|
39
|
+
*/
|
|
40
|
+
import type { ExtensionHost, Extension } from "../kernel/protocols.js";
|
|
41
|
+
export declare class PortfolioExtension implements Extension {
|
|
42
|
+
name: string;
|
|
43
|
+
version: string;
|
|
44
|
+
register(kernel: ExtensionHost): void;
|
|
45
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PortfolioExtension — DNA Cloud portfolio-console data foundation.
|
|
3
|
+
*
|
|
4
|
+
* 1:1 parity with Python `dna.extensions.portfolio`.
|
|
5
|
+
*
|
|
6
|
+
* Registers 5 record Kinds, from descriptors (F3 — record Kinds are data, not
|
|
7
|
+
* classes). The accepted model (adr-portfolio-project-model): an Organization
|
|
8
|
+
* (the tenant boundary) owns Projects; a Project is a multi-repo CONTAINER that
|
|
9
|
+
* owns its board scope + intel sources + memory; RBAC is the standard ladder.
|
|
10
|
+
*
|
|
11
|
+
* - Organization (`portfolio-org`) — the tenant's org profile, the
|
|
12
|
+
* enterprise-familiar top-level container the console aggregates. One per
|
|
13
|
+
* tenant. Distinct from the platform-level `Tenant` provisioning identity
|
|
14
|
+
* Kind (GLOBAL); this is the editable profile inside the tenant's portfolio.
|
|
15
|
+
* - Project (`portfolio-project`) — the KEY Kind: the multi-repo
|
|
16
|
+
* development-space container that OWNS a board scope (`<slug>-development`),
|
|
17
|
+
* IntelSources and memory, and is the permission boundary. Repos are
|
|
18
|
+
* attached BY REFERENCE via `repo_refs` (the N—N edge lives on the Project
|
|
19
|
+
* side).
|
|
20
|
+
* - Repo (`portfolio-repo`) — a code repository the portfolio references.
|
|
21
|
+
* Attached to N Projects via `Project.repo_refs`; carries NO project
|
|
22
|
+
* back-ref (single source of truth for the N—N edge → no duplication).
|
|
23
|
+
* - Membership (`portfolio-membership`) — the RBAC join: a user's role at an
|
|
24
|
+
* org- or project-scope (standard ladder owner > admin > member > guest,
|
|
25
|
+
* highest-role-wins, org-owner superuser). Distinct from the tenant Kind
|
|
26
|
+
* `TenantMembership` (which links a user to a provisioning Tenant).
|
|
27
|
+
* - Role (`portfolio-role`) — the role ladder AS DATA (the DNA thesis):
|
|
28
|
+
* each rung a doc with `rank` + `capabilities`, so the ladder is extensible
|
|
29
|
+
* (custom roles) rather than a hardcoded enum. The four standard rungs ship
|
|
30
|
+
* as per-tenant seed docs (examples/dna-cloud/.dna/.../roles/).
|
|
31
|
+
*
|
|
32
|
+
* All 5 are TENANTED — per-tenant portfolio data, NOT shared `_lib` defaults,
|
|
33
|
+
* and deliberately NOT inheritable (never in DEFAULT_INHERITABLE_KINDS_V1), so
|
|
34
|
+
* TENANTED is the correct tenancy.
|
|
35
|
+
*
|
|
36
|
+
* This is the data foundation ONLY — the console UI, the resolve_role helper
|
|
37
|
+
* (highest-role-wins + org-owner superuser) and the enterprise SSO/SCIM layer
|
|
38
|
+
* land in later stories; here we ship just the five data Kinds.
|
|
39
|
+
*/
|
|
40
|
+
import { loadDescriptors } from "../kernel/descriptor-loader.js";
|
|
41
|
+
export class PortfolioExtension {
|
|
42
|
+
name = "portfolio";
|
|
43
|
+
version = "1.0.0";
|
|
44
|
+
register(kernel) {
|
|
45
|
+
// F3: all 5 Kinds ship as kinds/*.kind.yaml package data (byte-identical
|
|
46
|
+
// Py↔TS mirror), registered through the SAME funnel as per-scope
|
|
47
|
+
// KindDefinitions (plane lint + digest idempotency + builtin conflict
|
|
48
|
+
// marker).
|
|
49
|
+
for (const raw of loadDescriptors(import.meta.url, "portfolio/kinds")) {
|
|
50
|
+
kernel.kindFromDescriptor(raw);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|