Skip to content

Commit c40e02e

Browse files
committed
wip: checking in
w# deleted: lib/foundry/auth/permissions_test.go
1 parent b0ca1e7 commit c40e02e

File tree

323 files changed

+4974
-49311
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

323 files changed

+4974
-49311
lines changed

configs/ory/keto/package-lock.json

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

configs/ory/keto/package.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"name": "keto",
3+
"version": "1.0.0",
4+
"description": "Keto permission structure (OPL) for Catalyst Forge",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"author": "Project Catalyst",
10+
"license": "MIT",
11+
"dependencies": {
12+
"@ory/keto-namespace-types": "^0.13.0-alpha.0"
13+
}
14+
}

configs/ory/keto/permissions.ts

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
// permissions.ts
2+
import { Namespace, Context } from "@ory/keto-namespace-types"
3+
4+
// Subjects
5+
export class User implements Namespace { }
6+
export class Client implements Namespace { }
7+
8+
// Root (singleton "forge")
9+
export class Global implements Namespace {
10+
related: {
11+
admins: (User | Client)[]
12+
members: (User | Client)[]
13+
}
14+
15+
permits = {
16+
// Global administrators (root-equivalent)
17+
admin: (ctx: Context): boolean =>
18+
this.related.admins.includes(ctx.subject),
19+
20+
// "Can read platform-wide things" (used to open cross-team read)
21+
read_all: (ctx: Context): boolean =>
22+
this.related.members.includes(ctx.subject) || this.permits.admin(ctx),
23+
}
24+
}
25+
26+
// Teams (frontend, backend, qa, sre, ...)
27+
export class Team implements Namespace {
28+
related: {
29+
parent: Global[] // always [forge]
30+
admins: (User | Client)[] // team admins
31+
maintainers: (User | Client)[] // can create/manage projects in this team
32+
members: (User | Client)[] // normal team members
33+
viewers: (User | Client)[] // optional: explicit viewer role
34+
}
35+
36+
permits = {
37+
// Team-level admin tasks (manage team membership, etc.)
38+
administer: (ctx: Context): boolean =>
39+
this.related.admins.includes(ctx.subject) ||
40+
this.related.parent.traverse((g) => g.permits.admin(ctx)),
41+
42+
// Read: team members, explicit viewers, or any global member (org-wide visibility)
43+
read: (ctx: Context): boolean =>
44+
this.related.members.includes(ctx.subject) ||
45+
this.related.viewers.includes(ctx.subject) ||
46+
this.related.parent.traverse((g) => g.permits.read_all(ctx)),
47+
48+
// Create/manage projects in this team
49+
maintain: (ctx: Context): boolean =>
50+
this.related.maintainers.includes(ctx.subject) ||
51+
this.permits.administer(ctx),
52+
}
53+
}
54+
55+
// Projects belong to a team
56+
export class Project implements Namespace {
57+
related: {
58+
team: Team[]
59+
admins: (User | Client)[]
60+
maintainers: (User | Client)[]
61+
builders: (User | Client)[]
62+
deployers: (User | Client)[]
63+
viewers: (User | Client)[]
64+
readers: (User | Client)[]
65+
}
66+
67+
permits = {
68+
// Full admin over the project
69+
administer: (ctx: Context): boolean =>
70+
this.related.admins.includes(ctx.subject) ||
71+
this.related.team.traverse((t) => t.permits.administer(ctx)),
72+
73+
74+
// Write / manage releases (but not necessarily deploy)
75+
maintain: (ctx: Context): boolean =>
76+
this.related.maintainers.includes(ctx.subject) ||
77+
this.permits.administer(ctx),
78+
79+
// Build: builders, or anyone who can maintain the project
80+
build: (ctx: Context): boolean =>
81+
this.related.builders.includes(ctx.subject) || this.permits.maintain(ctx),
82+
83+
// Can initiate deployment (project side - env check happens at Deployment)
84+
deploy: (ctx: Context): boolean =>
85+
this.related.deployers.includes(ctx.subject) ||
86+
this.permits.maintain(ctx),
87+
88+
// Read: readers, or anyone who can read the team, or any global member (cross-team visibility)
89+
read: (ctx: Context): boolean =>
90+
this.related.readers.includes(ctx.subject) ||
91+
this.related.team.traverse((t) => t.permits.read(ctx)),
92+
}
93+
}
94+
95+
// Releases belong to a project
96+
export class Release implements Namespace {
97+
related: {
98+
project: Project[]
99+
owners: (User | Client)[]
100+
maintainers: (User | Client)[]
101+
deployers: (User | Client)[]
102+
readers: (User | Client)[]
103+
}
104+
105+
permits = {
106+
administer: (ctx: Context): boolean =>
107+
this.related.owners.includes(ctx.subject) ||
108+
this.related.project.traverse((p) => p.permits.administer(ctx)),
109+
110+
maintain: (ctx: Context): boolean =>
111+
this.related.maintainers.includes(ctx.subject) ||
112+
this.permits.administer(ctx),
113+
114+
deploy: (ctx: Context): boolean =>
115+
this.related.deployers.includes(ctx.subject) ||
116+
this.permits.maintain(ctx) ||
117+
this.related.project.traverse((p) => p.permits.deploy(ctx)),
118+
119+
read: (ctx: Context): boolean =>
120+
this.related.readers.includes(ctx.subject) ||
121+
this.permits.maintain(ctx) ||
122+
this.related.project.traverse((p) => p.permits.read(ctx)),
123+
}
124+
}
125+
126+
// Environments are shared infra (dev, preprod, prod)
127+
export class Environment implements Namespace {
128+
related: {
129+
parent: Global[] // always [forge]
130+
admins: (User | Client)[]
131+
deployers: (User | Client)[]
132+
readers: (User | Client)[]
133+
}
134+
135+
permits = {
136+
administer: (ctx: Context): boolean =>
137+
this.related.admins.includes(ctx.subject) ||
138+
this.related.parent.traverse((g) => g.permits.admin(ctx)),
139+
140+
deploy: (ctx: Context): boolean =>
141+
this.related.deployers.includes(ctx.subject) || this.permits.administer(ctx),
142+
143+
read: (ctx: Context): boolean =>
144+
this.related.readers.includes(ctx.subject) ||
145+
this.related.parent.traverse((g) => g.permits.read_all(ctx)),
146+
}
147+
}
148+
149+
// Deployment references BOTH a release and an environment
150+
export class Deployment implements Namespace {
151+
related: {
152+
release: Release[]
153+
environment: Environment[]
154+
readers: (User | Client)[] // optional: explicit readers
155+
}
156+
157+
permits = {
158+
// operate == "allowed to trigger / approve / rollback a deploy"
159+
operate: (ctx: Context): boolean =>
160+
// need BOTH: release permission to deploy AND environment permission to deploy
161+
(this.related.release.traverse((r) => r.permits.deploy(ctx)) &&
162+
this.related.environment.traverse((e) => e.permits.deploy(ctx))) ||
163+
// always allow global admins
164+
this.related.environment.traverse((e) =>
165+
e.related.parent.traverse((g) => g.permits.admin(ctx))
166+
),
167+
168+
// read if you can read the release or environment (or explicit readers)
169+
read: (ctx: Context): boolean =>
170+
this.related.readers.includes(ctx.subject) ||
171+
this.related.release.traverse((r) => r.permits.read(ctx)) ||
172+
this.related.environment.traverse((e) => e.permits.read(ctx)),
173+
}
174+
}

lib/foundry/auth/Earthfile

Lines changed: 0 additions & 38 deletions
This file was deleted.

lib/foundry/auth/blueprint.cue

Lines changed: 0 additions & 1 deletion
This file was deleted.

lib/foundry/auth/github/cache_test.go

Lines changed: 0 additions & 127 deletions
This file was deleted.

0 commit comments

Comments
 (0)