dna-sdk 0.11.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 +2 -0
- package/dist/extensions/guardrails.js +4 -0
- package/dist/extensions/helix.js +19 -6
- 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/index.d.ts +1 -0
- package/dist/kernel/composition-resolver.js +17 -1
- package/dist/kernel/index.d.ts +6 -0
- package/dist/kernel/index.js +13 -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
package/dist/bootstrap.js
CHANGED
|
@@ -42,6 +42,7 @@ import { CloudExtension } from "./extensions/cloud.js";
|
|
|
42
42
|
import { AutomationExtension } from "./extensions/automation.js";
|
|
43
43
|
import { EvalExtension } from "./extensions/eval.js";
|
|
44
44
|
import { IntelExtension } from "./extensions/intel.js";
|
|
45
|
+
import { PortfolioExtension } from "./extensions/portfolio.js";
|
|
45
46
|
import { loadConfig } from "./config.js";
|
|
46
47
|
import { resolveDefaultFsUrl, sourceFromUrl } from "./adapters/source-url.js";
|
|
47
48
|
/**
|
|
@@ -75,6 +76,7 @@ function loadBuiltins(target) {
|
|
|
75
76
|
new AutomationExtension(),
|
|
76
77
|
new EvalExtension(),
|
|
77
78
|
new IntelExtension(),
|
|
79
|
+
new PortfolioExtension(),
|
|
78
80
|
]) {
|
|
79
81
|
target.load(ext);
|
|
80
82
|
}
|
|
@@ -21,6 +21,10 @@ class GuardrailKind extends KindBase {
|
|
|
21
21
|
promptTargetPriority = 0;
|
|
22
22
|
flattenInContext = false;
|
|
23
23
|
descriptionFallbackField = "instruction";
|
|
24
|
+
// Validate on read/compose, not only on write (i-validation-shallow) β parity
|
|
25
|
+
// with Python GuardrailKind.validate_on_parse. parse() below already throws on
|
|
26
|
+
// a bad severity/scope via GuardrailSchema (z.enum); this declares the intent.
|
|
27
|
+
validateOnParse = true;
|
|
24
28
|
storage = SD.bundle("guardrails", "GUARDRAIL.md", "list", "rules");
|
|
25
29
|
graphStyle = { fill: "#EF4444", stroke: "#DC2626", textColor: "#fff" };
|
|
26
30
|
asciiIcon = "π‘οΈ";
|
package/dist/extensions/helix.js
CHANGED
|
@@ -30,11 +30,23 @@ const GUARDRAILS_BLOCK = "{{#guardrails-guardrail}}" +
|
|
|
30
30
|
"{{#description}}_{{description}}_\n\n{{/description}}" +
|
|
31
31
|
"{{#rules}}- {{{.}}}\n{{/rules}}\n" +
|
|
32
32
|
"{{/guardrails-guardrail}}";
|
|
33
|
+
// Skills block (i-031) β a referenced Skill COMPOSES into the system prompt,
|
|
34
|
+
// exactly like Guardrails: a Mustache section over the dep-filtered
|
|
35
|
+
// `agentskills-skill` list, inlining each skill's SKILL.md body. Before this
|
|
36
|
+
// fix a wired Skill was inert (in context, rendered by no layout). Skills
|
|
37
|
+
// land AFTER the soul and BEFORE guardrails; a skill-less agent renders the
|
|
38
|
+
// empty section to nothing, composing byte-identically to before. 1:1 with
|
|
39
|
+
// Python `_SKILLS_BLOCK`.
|
|
40
|
+
const SKILLS_BLOCK = "{{#agentskills-skill}}" +
|
|
41
|
+
"## Skill: {{name}}\n" +
|
|
42
|
+
"{{#description}}_{{description}}_\n\n{{/description}}" +
|
|
43
|
+
"{{{instruction}}}\n\n" +
|
|
44
|
+
"{{/agentskills-skill}}";
|
|
33
45
|
// instruction-first (a.k.a. "default") β historic order: instruction, soul,
|
|
34
|
-
// guardrails. IS the kind default template.
|
|
35
|
-
const LAYOUT_INSTRUCTION_FIRST = "{{{agent.instruction}}}\n\n{{{soul_content}}}\n\n" + GUARDRAILS_BLOCK;
|
|
36
|
-
// persona-first β Soul leads, then instruction, then guardrails.
|
|
37
|
-
const LAYOUT_PERSONA_FIRST = "{{{soul_content}}}\n\n{{{agent.instruction}}}\n\n" + GUARDRAILS_BLOCK;
|
|
46
|
+
// skills, guardrails. IS the kind default template.
|
|
47
|
+
const LAYOUT_INSTRUCTION_FIRST = "{{{agent.instruction}}}\n\n{{{soul_content}}}\n\n" + SKILLS_BLOCK + GUARDRAILS_BLOCK;
|
|
48
|
+
// persona-first β Soul leads, then instruction, then skills, then guardrails.
|
|
49
|
+
const LAYOUT_PERSONA_FIRST = "{{{soul_content}}}\n\n{{{agent.instruction}}}\n\n" + SKILLS_BLOCK + GUARDRAILS_BLOCK;
|
|
38
50
|
const AGENT_LAYOUTS = {
|
|
39
51
|
default: LAYOUT_INSTRUCTION_FIRST,
|
|
40
52
|
"instruction-first": LAYOUT_INSTRUCTION_FIRST,
|
|
@@ -342,8 +354,9 @@ class AgentKind extends KindBase {
|
|
|
342
354
|
promptTemplate() {
|
|
343
355
|
// IS the `instruction-first` / `default` named layout β the kind default
|
|
344
356
|
// template and the `default` layout are one string, so an agent with no
|
|
345
|
-
// `layout:` composes identically.
|
|
346
|
-
//
|
|
357
|
+
// `layout:` composes identically. Includes the skills block (i-031) and
|
|
358
|
+
// the guardrails block β Soul, Skills, and Guardrails all compose into the
|
|
359
|
+
// prompt. See the layout-constants comment above.
|
|
347
360
|
return LAYOUT_INSTRUCTION_FIRST;
|
|
348
361
|
}
|
|
349
362
|
layoutTemplate(name) {
|
|
@@ -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
|
+
}
|