@noodleseed/one 0.121.0 → 0.122.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/commands/session.d.ts.map +1 -1
- package/dist/commands/session.js +5 -2
- package/dist/commands/session.js.map +1 -1
- package/node_modules/@noodle-borg/agent-kit/dist/generated/example-files.js +1 -1
- package/node_modules/@noodle-borg/agent-kit/dist/generated/example-files.js.map +1 -1
- package/node_modules/@noodle-borg/agent-kit/dist/plugin-marketplace-docs.js +4 -4
- package/node_modules/@noodle-borg/agent-kit/dist/plugin-submission.js +8 -8
- package/node_modules/@noodle-borg/agent-kit/dist/plugin-submission.js.map +1 -1
- package/node_modules/@noodle-borg/agent-kit/dist/skill-operations-refs.js +1 -1
- package/node_modules/@noodle-borg/agent-kit/dist/skill-operations-refs.js.map +1 -1
- package/node_modules/@noodle-borg/agent-kit/package.json +1 -1
- package/node_modules/@noodle-borg/assistant-gateway/package.json +1 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/contracts.d.ts +30 -9
- package/node_modules/@noodle-borg/developer-mcp/dist/contracts.d.ts.map +1 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/contracts.js +21 -6
- package/node_modules/@noodle-borg/developer-mcp/dist/contracts.js.map +1 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/port.d.ts +2 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/port.d.ts.map +1 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/port.js.map +1 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/prompts.js +3 -3
- package/node_modules/@noodle-borg/developer-mcp/dist/prompts.js.map +1 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/resources.d.ts.map +1 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/resources.js +10 -9
- package/node_modules/@noodle-borg/developer-mcp/dist/resources.js.map +1 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/results.d.ts +4 -3
- package/node_modules/@noodle-borg/developer-mcp/dist/results.d.ts.map +1 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/results.js +5 -19
- package/node_modules/@noodle-borg/developer-mcp/dist/results.js.map +1 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/server.js +3 -3
- package/node_modules/@noodle-borg/developer-mcp/dist/server.js.map +1 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/tools/apps.d.ts.map +1 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/tools/apps.js +6 -25
- package/node_modules/@noodle-borg/developer-mcp/dist/tools/apps.js.map +1 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/tools/context.d.ts +16 -3
- package/node_modules/@noodle-borg/developer-mcp/dist/tools/context.d.ts.map +1 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/tools/context.js +22 -19
- package/node_modules/@noodle-borg/developer-mcp/dist/tools/context.js.map +1 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/tools/deployments.d.ts.map +1 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/tools/deployments.js +3 -9
- package/node_modules/@noodle-borg/developer-mcp/dist/tools/deployments.js.map +1 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/tools/diagnose.d.ts.map +1 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/tools/diagnose.js +15 -16
- package/node_modules/@noodle-borg/developer-mcp/dist/tools/diagnose.js.map +1 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/tools/operations.d.ts.map +1 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/tools/operations.js +9 -17
- package/node_modules/@noodle-borg/developer-mcp/dist/tools/operations.js.map +1 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/tools/rollback.d.ts.map +1 -1
- package/node_modules/@noodle-borg/developer-mcp/dist/tools/rollback.js +7 -10
- package/node_modules/@noodle-borg/developer-mcp/dist/tools/rollback.js.map +1 -1
- package/node_modules/@noodle-borg/knowledge/dist/budget.d.ts +41 -17
- package/node_modules/@noodle-borg/knowledge/dist/budget.d.ts.map +1 -1
- package/node_modules/@noodle-borg/knowledge/dist/budget.js +0 -0
- package/node_modules/@noodle-borg/knowledge/dist/budget.js.map +1 -1
- package/node_modules/@noodle-borg/knowledge/dist/index.d.ts +1 -0
- package/node_modules/@noodle-borg/knowledge/dist/index.d.ts.map +1 -1
- package/node_modules/@noodle-borg/knowledge/dist/index.js +1 -0
- package/node_modules/@noodle-borg/knowledge/dist/index.js.map +1 -1
- package/node_modules/@noodle-borg/knowledge/dist/postgres-budget-store.d.ts +22 -0
- package/node_modules/@noodle-borg/knowledge/dist/postgres-budget-store.d.ts.map +1 -0
- package/node_modules/@noodle-borg/knowledge/dist/postgres-budget-store.js +102 -0
- package/node_modules/@noodle-borg/knowledge/dist/postgres-budget-store.js.map +1 -0
- package/node_modules/@noodle-borg/knowledge/dist/postgres-revision-store.d.ts +5 -3
- package/node_modules/@noodle-borg/knowledge/dist/postgres-revision-store.d.ts.map +1 -1
- package/node_modules/@noodle-borg/knowledge/dist/postgres-revision-store.js +61 -1
- package/node_modules/@noodle-borg/knowledge/dist/postgres-revision-store.js.map +1 -1
- package/node_modules/@noodle-borg/knowledge/dist/revision-store.d.ts +28 -1
- package/node_modules/@noodle-borg/knowledge/dist/revision-store.d.ts.map +1 -1
- package/node_modules/@noodle-borg/knowledge/dist/revision-store.js +39 -0
- package/node_modules/@noodle-borg/knowledge/dist/revision-store.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/auth/developer-grant-guard.d.ts +6 -4
- package/node_modules/@noodle-borg/service/dist/auth/developer-grant-guard.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/auth/developer-grant-guard.js +13 -16
- package/node_modules/@noodle-borg/service/dist/auth/developer-grant-guard.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/developer-mcp/control-plane-adapter.d.ts +3 -2
- package/node_modules/@noodle-borg/service/dist/developer-mcp/control-plane-adapter.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/developer-mcp/control-plane-adapter.js +66 -47
- package/node_modules/@noodle-borg/service/dist/developer-mcp/control-plane-adapter.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/developer-mcp/mount.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/developer-mcp/mount.js +15 -16
- package/node_modules/@noodle-borg/service/dist/developer-mcp/mount.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/index.d.ts +2 -2
- package/node_modules/@noodle-borg/service/dist/index.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/index.js +1 -1
- package/node_modules/@noodle-borg/service/dist/index.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/consent-claims.d.ts +0 -2
- package/node_modules/@noodle-borg/service/dist/oauth/consent-claims.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/consent-claims.js +0 -16
- package/node_modules/@noodle-borg/service/dist/oauth/consent-claims.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/developer-grant-authorizer.d.ts +3 -28
- package/node_modules/@noodle-borg/service/dist/oauth/developer-grant-authorizer.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/developer-grant-authorizer.js +8 -67
- package/node_modules/@noodle-borg/service/dist/oauth/developer-grant-authorizer.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/developer-grant-bootstrap.d.ts +0 -4
- package/node_modules/@noodle-borg/service/dist/oauth/developer-grant-bootstrap.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/developer-grant-bootstrap.js +1 -14
- package/node_modules/@noodle-borg/service/dist/oauth/developer-grant-bootstrap.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/developer-grant-flow.d.ts +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/developer-grant-flow.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/developer-grant-flow.js +45 -36
- package/node_modules/@noodle-borg/service/dist/oauth/developer-grant-flow.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/developer-grant-page.d.ts +2 -2
- package/node_modules/@noodle-borg/service/dist/oauth/developer-grant-page.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/developer-grant-page.js +20 -229
- package/node_modules/@noodle-borg/service/dist/oauth/developer-grant-page.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/developer-grant-store-postgres.d.ts +3 -2
- package/node_modules/@noodle-borg/service/dist/oauth/developer-grant-store-postgres.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/developer-grant-store-postgres.js +70 -36
- package/node_modules/@noodle-borg/service/dist/oauth/developer-grant-store-postgres.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/developer-grant.d.ts +17 -6
- package/node_modules/@noodle-borg/service/dist/oauth/developer-grant.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/developer-grant.js +98 -26
- package/node_modules/@noodle-borg/service/dist/oauth/developer-grant.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/service-bootstrap.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/service-bootstrap.js +0 -2
- package/node_modules/@noodle-borg/service/dist/oauth/service-bootstrap.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/upstream-consent.js +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/upstream-consent.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/analytics.js +3 -3
- package/node_modules/@noodle-borg/service/dist/routes/analytics.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/apps.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/apps.js +6 -27
- package/node_modules/@noodle-borg/service/dist/routes/apps.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/config-values.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/config-values.js +5 -8
- package/node_modules/@noodle-borg/service/dist/routes/config-values.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/control-plane.d.ts +7 -6
- package/node_modules/@noodle-borg/service/dist/routes/control-plane.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/control-plane.js +7 -6
- package/node_modules/@noodle-borg/service/dist/routes/control-plane.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/deploy-preflight.js +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/deploy-preflight.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/deployment-package.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/deployment-package.js +2 -7
- package/node_modules/@noodle-borg/service/dist/routes/deployment-package.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/deployments.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/deployments.js +7 -20
- package/node_modules/@noodle-borg/service/dist/routes/deployments.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/diagnostics.js +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/diagnostics.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/envs.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/envs.js +4 -8
- package/node_modules/@noodle-borg/service/dist/routes/envs.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/logs.js +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/logs.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/rollback.js +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/rollback.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/store/postgres-schema.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/store/postgres-schema.js +21 -0
- package/node_modules/@noodle-borg/service/dist/store/postgres-schema.js.map +1 -1
- package/node_modules/@noodle-borg/service/package.json +1 -1
- package/node_modules/@noodleseed/assistant/package.json +41 -16
- package/package.json +2 -2
|
@@ -1,246 +1,37 @@
|
|
|
1
1
|
import { renderOAuthPage } from './branding.js';
|
|
2
2
|
const CAPABILITY_COPY = {
|
|
3
3
|
'cloud:read': 'Read cloud apps, deployments, logs, analytics, and diagnostics',
|
|
4
|
-
'deployments:write': 'Build and deploy apps
|
|
5
|
-
'deployments:rollback': 'Roll back deployments',
|
|
6
|
-
'config:write': 'Set and remove variables and secrets
|
|
4
|
+
'deployments:write': 'Build and deploy apps',
|
|
5
|
+
'deployments:rollback': 'Roll back deployments when you are an organization owner',
|
|
6
|
+
'config:write': 'Set and remove variables and secrets (never read a secret back)',
|
|
7
7
|
};
|
|
8
|
-
const ENVIRONMENT_PRIORITY = {
|
|
9
|
-
dev: 0,
|
|
10
|
-
staging: 1,
|
|
11
|
-
prod: 3,
|
|
12
|
-
};
|
|
13
|
-
const DEVELOPER_GRANT_STYLES = `
|
|
14
|
-
.ns-card{width:min(100%,46rem)}
|
|
15
|
-
.ns-title{max-width:38rem;white-space:normal}
|
|
16
|
-
.developer-context{grid-template-columns:repeat(3,minmax(0,1fr));gap:.75rem;margin-bottom:1.55rem}
|
|
17
|
-
.developer-context>div{min-width:0}
|
|
18
|
-
.developer-context .ns-dd{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
19
|
-
.developer-grant{display:grid;gap:1.35rem}
|
|
20
|
-
.developer-section{min-width:0;margin:0;padding:0;border:0}
|
|
21
|
-
.developer-step{display:flex;align-items:center;gap:.6rem;margin:0 0 .3rem;color:var(--fg);font-size:.94rem;font-weight:650}
|
|
22
|
-
.developer-step-number{display:grid;place-items:center;width:1.6rem;height:1.6rem;border:1px solid var(--border);border-radius:999px;color:var(--orange);font-size:.72rem}
|
|
23
|
-
.developer-help{margin:0 0 .8rem;color:var(--muted);font-size:.8rem;line-height:1.5}
|
|
24
|
-
.developer-org-list{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.65rem}
|
|
25
|
-
.developer-org-choice{position:relative;display:block;min-width:0;cursor:pointer}
|
|
26
|
-
.developer-org-choice>input{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
|
|
27
|
-
.developer-org-card{display:flex;align-items:center;justify-content:space-between;gap:.85rem;min-height:4rem;padding:.85rem .95rem;border:1px solid var(--border);border-radius:.8rem;background:rgba(255,255,255,.025);transition:border-color .16s ease,background .16s ease,box-shadow .16s ease}
|
|
28
|
-
.developer-org-choice:hover .developer-org-card{border-color:color-mix(in srgb,var(--border),var(--fg) 20%);background:rgba(255,255,255,.04)}
|
|
29
|
-
.developer-org-choice>input:focus-visible+.developer-org-card{outline:2px solid var(--orange);outline-offset:2px}
|
|
30
|
-
.developer-org-choice>input:checked+.developer-org-card{border-color:color-mix(in srgb,var(--orange) 70%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--orange) 13%,transparent),rgba(255,255,255,.025));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--orange) 12%,transparent)}
|
|
31
|
-
.developer-org-name{display:block;overflow:hidden;color:var(--fg);font-size:.88rem;font-weight:650;text-overflow:ellipsis;white-space:nowrap}
|
|
32
|
-
.developer-org-access{display:block;margin-top:.18rem;color:var(--muted);font-size:.72rem}
|
|
33
|
-
.developer-choice-mark{display:grid;flex:0 0 auto;place-items:center;width:1.1rem;height:1.1rem;border:1px solid var(--border);border-radius:999px;color:transparent;font-size:.65rem}
|
|
34
|
-
.developer-org-choice>input:checked+.developer-org-card .developer-choice-mark{border-color:var(--orange);background:var(--orange);color:#130b07}
|
|
35
|
-
.developer-environment-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:.6rem}
|
|
36
|
-
.developer-environment{position:relative;display:block;min-width:0;cursor:pointer}
|
|
37
|
-
.developer-environment>input{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
|
|
38
|
-
.developer-environment-card{display:flex;align-items:flex-start;gap:.65rem;min-height:4.1rem;padding:.8rem;border:1px solid var(--border);border-radius:.75rem;background:rgba(255,255,255,.025);transition:border-color .16s ease,background .16s ease}
|
|
39
|
-
.developer-environment:hover .developer-environment-card{border-color:color-mix(in srgb,var(--border),var(--fg) 20%);background:rgba(255,255,255,.04)}
|
|
40
|
-
.developer-environment>input:focus-visible+.developer-environment-card{outline:2px solid var(--orange);outline-offset:2px}
|
|
41
|
-
.developer-environment>input:checked+.developer-environment-card{border-color:color-mix(in srgb,var(--orange) 70%,transparent);background:color-mix(in srgb,var(--orange) 10%,transparent)}
|
|
42
|
-
.developer-checkbox{display:grid;flex:0 0 auto;place-items:center;width:1rem;height:1rem;margin-top:.08rem;border:1px solid var(--border);border-radius:.25rem;color:transparent;font-size:.68rem}
|
|
43
|
-
.developer-environment>input:checked+.developer-environment-card .developer-checkbox{border-color:var(--orange);background:var(--orange);color:#130b07}
|
|
44
|
-
.developer-environment-name{display:block;color:var(--fg);font-size:.84rem;font-weight:650}
|
|
45
|
-
.developer-environment-note{display:block;margin-top:.2rem;color:var(--muted);font-size:.68rem;line-height:1.35}
|
|
46
|
-
.developer-environment-note.is-production{color:#f1a273}
|
|
47
|
-
.developer-capabilities{margin:.75rem 0 0;padding:.7rem .8rem;border:1px solid var(--border);border-radius:.7rem;background:rgba(0,0,0,.12);color:var(--muted);font-size:.75rem}
|
|
48
|
-
.developer-capabilities summary{cursor:pointer;color:var(--fg);font-weight:600}
|
|
49
|
-
.developer-capabilities ul{display:grid;gap:.35rem;margin:.6rem 0 0;padding-left:1.15rem;line-height:1.45}
|
|
50
|
-
.developer-summary{padding:.85rem .95rem;border:1px solid var(--border);border-radius:.75rem;background:rgba(255,255,255,.025)}
|
|
51
|
-
.developer-summary-label{margin:0 0 .24rem;color:var(--muted);font-size:.65rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase}
|
|
52
|
-
.developer-summary-copy{margin:0;color:var(--fg);font-size:.8rem;line-height:1.5}
|
|
53
|
-
.developer-selection-error{margin:.45rem 0 0;color:#f1a273;font-size:.75rem}
|
|
54
|
-
.developer-grant .ns-row{margin-top:0}
|
|
55
|
-
.developer-grant .btn-primary:disabled{cursor:not-allowed;filter:none;opacity:.45}
|
|
56
|
-
@media(max-width:680px){
|
|
57
|
-
.ns-card{padding:1.35rem}
|
|
58
|
-
.developer-context,.developer-org-list,.developer-environment-grid{grid-template-columns:1fr}
|
|
59
|
-
.developer-context{gap:.55rem}
|
|
60
|
-
}
|
|
61
|
-
`;
|
|
62
|
-
const DEVELOPER_GRANT_SCRIPT = `<script>
|
|
63
|
-
(function(){
|
|
64
|
-
var form=document.querySelector('[data-developer-grant]');
|
|
65
|
-
if(!form)return;
|
|
66
|
-
var choices=Array.from(form.querySelectorAll('[data-org-choice]'));
|
|
67
|
-
var panels=Array.from(form.querySelectorAll('[data-org-panel]'));
|
|
68
|
-
var authorize=form.querySelector('[data-authorize]');
|
|
69
|
-
var summary=form.querySelector('[data-selection-summary]');
|
|
70
|
-
var error=form.querySelector('[data-selection-error]');
|
|
71
|
-
var clientName=form.getAttribute('data-client-name')||'The developer plugin';
|
|
72
|
-
function activeIndex(){
|
|
73
|
-
var selected=choices.find(function(choice){return choice.checked;});
|
|
74
|
-
return selected ? Number(selected.getAttribute('data-org-choice')) : -1;
|
|
75
|
-
}
|
|
76
|
-
function activeEnvironments(){
|
|
77
|
-
var panel=panels[activeIndex()];
|
|
78
|
-
return panel ? Array.from(panel.querySelectorAll('input[name="environment"]:checked')).map(function(input){return input.value;}) : [];
|
|
79
|
-
}
|
|
80
|
-
function naturalList(values){
|
|
81
|
-
if(values.length<2)return values[0]||'';
|
|
82
|
-
if(values.length===2)return values[0]+' and '+values[1];
|
|
83
|
-
return values.slice(0,-1).join(', ')+', and '+values[values.length-1];
|
|
84
|
-
}
|
|
85
|
-
function update(){
|
|
86
|
-
var panel=panels[activeIndex()];
|
|
87
|
-
var environments=activeEnvironments();
|
|
88
|
-
var valid=panel!==undefined&&environments.length>0;
|
|
89
|
-
authorize.disabled=!valid;
|
|
90
|
-
error.hidden=valid;
|
|
91
|
-
if(valid){
|
|
92
|
-
summary.textContent=clientName+' can '+panel.getAttribute('data-capability-summary')+' in '+panel.getAttribute('data-org-name')+' for '+naturalList(environments)+'.';
|
|
93
|
-
}else{
|
|
94
|
-
summary.textContent='Select at least one environment to continue.';
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
choices.forEach(function(choice){
|
|
98
|
-
choice.addEventListener('change',function(){
|
|
99
|
-
var next=activeIndex();
|
|
100
|
-
panels.forEach(function(panel,index){
|
|
101
|
-
var active=index===next;
|
|
102
|
-
panel.hidden=!active;
|
|
103
|
-
var environments=Array.from(panel.querySelectorAll('input[name="environment"]'));
|
|
104
|
-
environments.forEach(function(environment){environment.checked=false;environment.disabled=!active;});
|
|
105
|
-
if(active){
|
|
106
|
-
var preferred=environments.find(function(environment){return environment.value==='dev';});
|
|
107
|
-
if(preferred)preferred.checked=true;
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
update();
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
form.addEventListener('change',function(event){
|
|
114
|
-
if(event.target&&event.target.matches('input[name="environment"]'))update();
|
|
115
|
-
});
|
|
116
|
-
form.addEventListener('submit',function(event){
|
|
117
|
-
var submitter=event.submitter;
|
|
118
|
-
if(submitter&&submitter.value==='deny')return;
|
|
119
|
-
if(activeEnvironments().length===0){event.preventDefault();update();}
|
|
120
|
-
});
|
|
121
|
-
update();
|
|
122
|
-
})();
|
|
123
|
-
</script>`;
|
|
124
8
|
export function renderDeveloperGrantPage(input) {
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const contentHtml = `<p class="ns-lede"
|
|
129
|
-
<dl class="ns-dl
|
|
130
|
-
<div><dt class="ns-dt">Signed in as</dt><dd class="ns-dd"
|
|
131
|
-
<div><dt class="ns-dt">Noodle Cloud</dt><dd class="ns-dd"
|
|
132
|
-
<div><dt class="ns-dt">Redirects to</dt><dd class="ns-dd"
|
|
9
|
+
const capabilities = input.capabilities
|
|
10
|
+
.map((capability) => `<li>${escapeHtml(CAPABILITY_COPY[capability])}</li>`)
|
|
11
|
+
.join('');
|
|
12
|
+
const contentHtml = `<p class="ns-lede"><strong>${escapeHtml(input.clientName)}</strong> wants to use your Noodle Seed developer access.</p>
|
|
13
|
+
<dl class="ns-dl">
|
|
14
|
+
<div><dt class="ns-dt">Signed in as</dt><dd class="ns-dd">${escapeHtml(input.userEmail)}</dd></div>
|
|
15
|
+
<div><dt class="ns-dt">Noodle Cloud</dt><dd class="ns-dd">${escapeHtml(input.resourceHost)}</dd></div>
|
|
16
|
+
<div><dt class="ns-dt">Redirects to</dt><dd class="ns-dd">${escapeHtml(input.redirectHost)}</dd></div>
|
|
133
17
|
</dl>
|
|
134
|
-
<
|
|
18
|
+
<p class="ns-note">This connection can operate in the organizations and environments you can currently access. Your access updates automatically when your membership or role changes.</p>
|
|
19
|
+
<ul>${capabilities}</ul>
|
|
20
|
+
<p class="ns-note">Only authorize if you recognize this application.</p>
|
|
21
|
+
<form method="post" action="${escapeHtml(input.grantAction)}">
|
|
135
22
|
<input type="hidden" name="grant_token" value="${escapeHtml(input.grantToken)}" />
|
|
136
|
-
|
|
23
|
+
<div class="ns-row">
|
|
24
|
+
<button type="submit" name="decision" value="deny" class="btn btn-ghost">Deny</button>
|
|
25
|
+
<span class="btn-glow"><button type="submit" name="decision" value="approve" class="btn btn-primary">Authorize</button></span>
|
|
26
|
+
</div>
|
|
137
27
|
</form>`;
|
|
138
28
|
return renderOAuthPage({
|
|
139
29
|
title: 'Authorize developer access — Noodle Seed',
|
|
140
30
|
kicker: 'Developer access',
|
|
141
|
-
heading: '
|
|
31
|
+
heading: 'Authorize Noodle Seed developer access',
|
|
142
32
|
contentHtml,
|
|
143
|
-
additionalStyles: DEVELOPER_GRANT_STYLES,
|
|
144
|
-
...(input.choices.length === 0 ? {} : { scriptHtml: DEVELOPER_GRANT_SCRIPT }),
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
function renderControls(input) {
|
|
148
|
-
const organizations = input.choices.map(renderOrganizationChoice).join('');
|
|
149
|
-
const panels = input.choices.map(renderEnvironmentPanel).join('');
|
|
150
|
-
const first = input.choices[0];
|
|
151
|
-
const initialEnvironment = first?.environments.includes('dev') ? 'dev' : first?.environments[0];
|
|
152
|
-
const initialSummary = first !== undefined && initialEnvironment !== undefined
|
|
153
|
-
? `${input.clientName} can ${capabilitySummary(first.capabilities)} in ${first.displayName ?? first.org} for ${initialEnvironment}.`
|
|
154
|
-
: 'Select at least one environment to continue.';
|
|
155
|
-
return `<fieldset class="developer-section">
|
|
156
|
-
<legend class="developer-step"><span class="developer-step-number">1</span>Choose organization</legend>
|
|
157
|
-
<p class="developer-help">Only one organization can be authorized in this connection.</p>
|
|
158
|
-
<div class="developer-org-list">${organizations}</div>
|
|
159
|
-
</fieldset>
|
|
160
|
-
<div>${panels}</div>
|
|
161
|
-
<div class="developer-summary" aria-live="polite">
|
|
162
|
-
<p class="developer-summary-label">Access summary</p>
|
|
163
|
-
<p class="developer-summary-copy" data-selection-summary>${escapeHtml(initialSummary)}</p>
|
|
164
|
-
<p class="developer-selection-error" data-selection-error hidden>Select at least one environment to continue.</p>
|
|
165
|
-
</div>
|
|
166
|
-
<div class="ns-row">
|
|
167
|
-
<button type="submit" name="decision" value="deny" class="btn btn-ghost">Deny</button>
|
|
168
|
-
<span class="btn-glow"><button type="submit" name="decision" value="approve" class="btn btn-primary" data-authorize>Authorize access</button></span>
|
|
169
|
-
</div>`;
|
|
170
|
-
}
|
|
171
|
-
function renderOrganizationChoice(choice, index) {
|
|
172
|
-
const label = choice.displayName ?? choice.org;
|
|
173
|
-
const access = choice.capabilities.includes('deployments:rollback')
|
|
174
|
-
? 'Owner access'
|
|
175
|
-
: 'Developer access';
|
|
176
|
-
return `<label class="developer-org-choice">
|
|
177
|
-
<input type="radio" name="org" value="${escapeHtml(choice.org)}" data-org-choice="${index}"${index === 0 ? ' checked' : ''} />
|
|
178
|
-
<span class="developer-org-card">
|
|
179
|
-
<span><span class="developer-org-name">${escapeHtml(label)}</span><span class="developer-org-access">${access}</span></span>
|
|
180
|
-
<span class="developer-choice-mark" aria-hidden="true">✓</span>
|
|
181
|
-
</span>
|
|
182
|
-
</label>`;
|
|
183
|
-
}
|
|
184
|
-
function renderEnvironmentPanel(choice, choiceIndex) {
|
|
185
|
-
const environments = orderedEnvironments(choice.environments)
|
|
186
|
-
.map((environment, environmentIndex) => renderEnvironment(environment, choiceIndex, environmentIndex, choiceIndex === 0))
|
|
187
|
-
.join('');
|
|
188
|
-
const capabilities = choice.capabilities
|
|
189
|
-
.map((capability) => `<li>${escapeHtml(CAPABILITY_COPY[capability])}</li>`)
|
|
190
|
-
.join('');
|
|
191
|
-
const label = choice.displayName ?? choice.org;
|
|
192
|
-
return `<section class="developer-section" data-org-panel="${choiceIndex}" data-org-name="${escapeHtml(label)}" data-capability-summary="${escapeHtml(capabilitySummary(choice.capabilities))}"${choiceIndex === 0 ? '' : ' hidden'}>
|
|
193
|
-
<h2 class="developer-step"><span class="developer-step-number">2</span>Choose environments</h2>
|
|
194
|
-
<p class="developer-help">Select every environment this plugin should be able to operate. Development is selected for you.</p>
|
|
195
|
-
<div class="developer-environment-grid">${environments}</div>
|
|
196
|
-
<details class="developer-capabilities">
|
|
197
|
-
<summary>What the plugin can do</summary>
|
|
198
|
-
<ul>${capabilities}</ul>
|
|
199
|
-
</details>
|
|
200
|
-
</section>`;
|
|
201
|
-
}
|
|
202
|
-
function renderEnvironment(environment, choiceIndex, environmentIndex, active) {
|
|
203
|
-
const id = `developer-environment-${choiceIndex}-${environmentIndex}`;
|
|
204
|
-
const selected = active && environment === 'dev';
|
|
205
|
-
const note = environmentNote(environment);
|
|
206
|
-
return `<label class="developer-environment" for="${id}">
|
|
207
|
-
<input id="${id}" type="checkbox" name="environment" value="${escapeHtml(environment)}"${selected ? ' checked' : ''}${active ? '' : ' disabled'} />
|
|
208
|
-
<span class="developer-environment-card">
|
|
209
|
-
<span class="developer-checkbox" aria-hidden="true">✓</span>
|
|
210
|
-
<span><span class="developer-environment-name">${escapeHtml(environment)}</span><span class="developer-environment-note${environment === 'prod' ? ' is-production' : ''}">${note}</span></span>
|
|
211
|
-
</span>
|
|
212
|
-
</label>`;
|
|
213
|
-
}
|
|
214
|
-
function orderedEnvironments(environments) {
|
|
215
|
-
return [...new Set(environments)].sort((left, right) => {
|
|
216
|
-
const leftPriority = ENVIRONMENT_PRIORITY[left] ?? 2;
|
|
217
|
-
const rightPriority = ENVIRONMENT_PRIORITY[right] ?? 2;
|
|
218
|
-
return leftPriority - rightPriority || left.localeCompare(right);
|
|
219
33
|
});
|
|
220
34
|
}
|
|
221
|
-
function environmentNote(environment) {
|
|
222
|
-
if (environment === 'dev')
|
|
223
|
-
return 'Recommended';
|
|
224
|
-
if (environment === 'prod')
|
|
225
|
-
return 'Can affect live users';
|
|
226
|
-
return 'Optional';
|
|
227
|
-
}
|
|
228
|
-
function capabilitySummary(capabilities) {
|
|
229
|
-
const actions = [];
|
|
230
|
-
if (capabilities.includes('cloud:read'))
|
|
231
|
-
actions.push('read cloud state');
|
|
232
|
-
if (capabilities.includes('deployments:write'))
|
|
233
|
-
actions.push('build and deploy apps');
|
|
234
|
-
if (capabilities.includes('config:write'))
|
|
235
|
-
actions.push('set variables and secrets');
|
|
236
|
-
if (capabilities.includes('deployments:rollback'))
|
|
237
|
-
actions.push('roll back deployments');
|
|
238
|
-
if (actions.length === 0)
|
|
239
|
-
return 'use its assigned capabilities';
|
|
240
|
-
if (actions.length === 1)
|
|
241
|
-
return actions[0] ?? 'use its assigned capabilities';
|
|
242
|
-
return `${actions.slice(0, -1).join(', ')} and ${actions.at(-1)}`;
|
|
243
|
-
}
|
|
244
35
|
function escapeHtml(value) {
|
|
245
36
|
return value
|
|
246
37
|
.replace(/&/g, '&')
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"developer-grant-page.js","sourceRoot":"","sources":["../../src/oauth/developer-grant-page.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"developer-grant-page.js","sourceRoot":"","sources":["../../src/oauth/developer-grant-page.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAYhD,MAAM,eAAe,GAAkD;IACrE,YAAY,EAAE,gEAAgE;IAC9E,mBAAmB,EAAE,uBAAuB;IAC5C,sBAAsB,EAAE,0DAA0D;IAClF,cAAc,EAAE,iEAAiE;CAClF,CAAC;AAEF,MAAM,UAAU,wBAAwB,CAAC,KAA8B;IACrE,MAAM,YAAY,GAAG,KAAK,CAAC,YAAY;SACpC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,OAAO,UAAU,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC;SAC1E,IAAI,CAAC,EAAE,CAAC,CAAC;IACZ,MAAM,WAAW,GAAG,8BAA8B,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC;;kEAEd,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC;kEAC3B,UAAU,CAAC,KAAK,CAAC,YAAY,CAAC;kEAC9B,UAAU,CAAC,KAAK,CAAC,YAAY,CAAC;;;UAGtF,YAAY;;kCAEY,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC;uDACR,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC;;;;;YAKvE,CAAC;IACX,OAAO,eAAe,CAAC;QACrB,KAAK,EAAE,0CAA0C;QACjD,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,wCAAwC;QACjD,WAAW;KACZ,CAAC,CAAC;AACL,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK;SACT,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC5B,CAAC"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { Pool } from 'pg';
|
|
2
|
-
import { type CreateDeveloperAccessGrant, type DeveloperAccessGrant, type DeveloperGrantFactoryOptions, type DeveloperGrantStore } from './developer-grant.js';
|
|
2
|
+
import { type ActiveDeveloperGrantLookup, type CreateDeveloperAccessGrant, type DeveloperAccessGrant, type DeveloperGrantFactoryOptions, type DeveloperGrantStore } from './developer-grant.js';
|
|
3
3
|
export declare class PostgresDeveloperGrantStore implements DeveloperGrantStore {
|
|
4
4
|
#private;
|
|
5
5
|
constructor(pool: Pool, options?: DeveloperGrantFactoryOptions);
|
|
6
6
|
initialize(): Promise<void>;
|
|
7
|
-
|
|
7
|
+
getOrCreateActive(input: CreateDeveloperAccessGrant): Promise<DeveloperAccessGrant>;
|
|
8
|
+
getActive(input: ActiveDeveloperGrantLookup): Promise<DeveloperAccessGrant | undefined>;
|
|
8
9
|
get(id: string): Promise<DeveloperAccessGrant | undefined>;
|
|
9
10
|
revoke(id: string, at: string): Promise<DeveloperAccessGrant | undefined>;
|
|
10
11
|
}
|
package/node_modules/@noodle-borg/service/dist/oauth/developer-grant-store-postgres.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"developer-grant-store-postgres.d.ts","sourceRoot":"","sources":["../../src/oauth/developer-grant-store-postgres.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAI/B,OAAO,EACL,KAAK,0BAA0B,EAE/B,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,EACjC,KAAK,mBAAmB,EAGzB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"developer-grant-store-postgres.d.ts","sourceRoot":"","sources":["../../src/oauth/developer-grant-store-postgres.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAI/B,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,0BAA0B,EAE/B,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,EACjC,KAAK,mBAAmB,EAGzB,MAAM,sBAAsB,CAAC;AAgB9B,qBAAa,2BAA4B,YAAW,mBAAmB;;gBAIzD,IAAI,EAAE,IAAI,EAAE,OAAO,GAAE,4BAAiC;IAK5D,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,iBAAiB,CAAC,KAAK,EAAE,0BAA0B,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAyDnF,SAAS,CAAC,KAAK,EAAE,0BAA0B,GAAG,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC;IAqBvF,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC;IAS1D,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC;CAYhF"}
|
|
@@ -3,11 +3,12 @@ import { z } from 'zod';
|
|
|
3
3
|
import { ensureDeveloperGrantSchema } from '../store/postgres-schema.js';
|
|
4
4
|
import { createDeveloperAccessGrantRecord, normalizeDeveloperAccessGrant, normalizeDeveloperGrantTimestamp, } from './developer-grant.js';
|
|
5
5
|
const developerGrantRowSchema = z.object({
|
|
6
|
+
grant_version: z.literal(2),
|
|
6
7
|
id: z.string(),
|
|
7
8
|
client_id: z.string(),
|
|
8
9
|
subject: z.string(),
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
resource: z.string(),
|
|
11
|
+
access_model: z.literal('live_user'),
|
|
11
12
|
capabilities: z.array(z.enum(DEVELOPER_CAPABILITIES)),
|
|
12
13
|
created_at: z.coerce.date(),
|
|
13
14
|
updated_at: z.coerce.date(),
|
|
@@ -24,38 +25,73 @@ export class PostgresDeveloperGrantStore {
|
|
|
24
25
|
async initialize() {
|
|
25
26
|
await ensureDeveloperGrantSchema(this.#pool);
|
|
26
27
|
}
|
|
27
|
-
async
|
|
28
|
+
async getOrCreateActive(input) {
|
|
28
29
|
const grant = createDeveloperAccessGrantRecord(input, this.#options);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
30
|
+
const existing = await this.getActive({
|
|
31
|
+
clientId: grant.clientId,
|
|
32
|
+
subject: grant.subject,
|
|
33
|
+
resource: grant.resource,
|
|
34
|
+
at: grant.createdAt,
|
|
35
|
+
});
|
|
36
|
+
if (existing !== undefined)
|
|
37
|
+
return existing;
|
|
38
|
+
// The partial uniqueness constraint deliberately treats an unrevoked row as active. Retire an
|
|
39
|
+
// expired tuple before inserting its replacement so persistence matches the in-memory contract.
|
|
40
|
+
await this.#pool.query(`UPDATE developer_access_grants
|
|
41
|
+
SET revoked_at = $4::timestamptz,
|
|
42
|
+
updated_at = $4::timestamptz
|
|
43
|
+
WHERE grant_version = 2
|
|
44
|
+
AND access_model = 'live_user'
|
|
45
|
+
AND client_id = $1
|
|
46
|
+
AND subject = $2
|
|
47
|
+
AND resource = $3
|
|
48
|
+
AND revoked_at IS NULL
|
|
49
|
+
AND expires_at <= $4::timestamptz`, [grant.clientId, grant.subject, grant.resource, grant.createdAt]);
|
|
50
|
+
const { rows } = await this.#pool.query(`INSERT INTO developer_access_grants
|
|
51
|
+
(id, client_id, subject, org_slug, environments, capabilities,
|
|
52
|
+
created_at, updated_at, expires_at, revoked_at,
|
|
53
|
+
grant_version, resource, access_model)
|
|
54
|
+
VALUES ($1, $2, $3, NULL, NULL, $4::jsonb, $5, $6, $7, NULL, 2, $8, 'live_user')
|
|
55
|
+
ON CONFLICT DO NOTHING
|
|
56
|
+
RETURNING *`, [
|
|
57
|
+
grant.id,
|
|
58
|
+
grant.clientId,
|
|
59
|
+
grant.subject,
|
|
60
|
+
JSON.stringify(grant.capabilities),
|
|
61
|
+
grant.createdAt,
|
|
62
|
+
grant.updatedAt,
|
|
63
|
+
grant.expiresAt ?? null,
|
|
64
|
+
grant.resource,
|
|
65
|
+
]);
|
|
66
|
+
if (rows[0] !== undefined)
|
|
46
67
|
return grantFromRow(rows[0]);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
68
|
+
const raced = await this.getActive({
|
|
69
|
+
clientId: grant.clientId,
|
|
70
|
+
subject: grant.subject,
|
|
71
|
+
resource: grant.resource,
|
|
72
|
+
at: grant.createdAt,
|
|
73
|
+
});
|
|
74
|
+
if (raced !== undefined)
|
|
75
|
+
return raced;
|
|
76
|
+
throw new Error(`developer grant "${grant.id}" already exists`);
|
|
77
|
+
}
|
|
78
|
+
async getActive(input) {
|
|
79
|
+
const at = normalizeDeveloperGrantTimestamp('authorization time', input.at ?? new Date().toISOString());
|
|
80
|
+
const { rows } = await this.#pool.query(`SELECT * FROM developer_access_grants
|
|
81
|
+
WHERE grant_version = 2
|
|
82
|
+
AND access_model = 'live_user'
|
|
83
|
+
AND client_id = $1
|
|
84
|
+
AND subject = $2
|
|
85
|
+
AND resource = $3
|
|
86
|
+
AND revoked_at IS NULL
|
|
87
|
+
AND (expires_at IS NULL OR expires_at > $4::timestamptz)
|
|
88
|
+
ORDER BY created_at DESC
|
|
89
|
+
LIMIT 1`, [input.clientId, input.subject, input.resource, at]);
|
|
90
|
+
return rows[0] === undefined ? undefined : grantFromRow(rows[0]);
|
|
54
91
|
}
|
|
55
92
|
async get(id) {
|
|
56
|
-
const { rows } = await this.#pool.query(
|
|
57
|
-
|
|
58
|
-
]);
|
|
93
|
+
const { rows } = await this.#pool.query(`SELECT * FROM developer_access_grants
|
|
94
|
+
WHERE id = $1 AND grant_version = 2 AND access_model = 'live_user'`, [id]);
|
|
59
95
|
return rows[0] === undefined ? undefined : grantFromRow(rows[0]);
|
|
60
96
|
}
|
|
61
97
|
async revoke(id, at) {
|
|
@@ -63,7 +99,7 @@ export class PostgresDeveloperGrantStore {
|
|
|
63
99
|
const { rows } = await this.#pool.query(`UPDATE developer_access_grants
|
|
64
100
|
SET updated_at = CASE WHEN revoked_at IS NULL THEN $2::timestamptz ELSE updated_at END,
|
|
65
101
|
revoked_at = COALESCE(revoked_at, $2::timestamptz)
|
|
66
|
-
WHERE id = $1
|
|
102
|
+
WHERE id = $1 AND grant_version = 2 AND access_model = 'live_user'
|
|
67
103
|
RETURNING *`, [id, revokedAt]);
|
|
68
104
|
return rows[0] === undefined ? undefined : grantFromRow(rows[0]);
|
|
69
105
|
}
|
|
@@ -71,11 +107,12 @@ export class PostgresDeveloperGrantStore {
|
|
|
71
107
|
function grantFromRow(value) {
|
|
72
108
|
const row = developerGrantRowSchema.parse(value);
|
|
73
109
|
return normalizeDeveloperAccessGrant({
|
|
110
|
+
version: 2,
|
|
74
111
|
id: row.id,
|
|
75
112
|
clientId: row.client_id,
|
|
76
113
|
subject: row.subject,
|
|
77
|
-
|
|
78
|
-
|
|
114
|
+
resource: row.resource,
|
|
115
|
+
accessModel: row.access_model,
|
|
79
116
|
capabilities: row.capabilities,
|
|
80
117
|
createdAt: row.created_at.toISOString(),
|
|
81
118
|
updatedAt: row.updated_at.toISOString(),
|
|
@@ -83,7 +120,4 @@ function grantFromRow(value) {
|
|
|
83
120
|
...(row.revoked_at === null ? {} : { revokedAt: row.revoked_at.toISOString() }),
|
|
84
121
|
});
|
|
85
122
|
}
|
|
86
|
-
function isUniqueViolation(error) {
|
|
87
|
-
return typeof error === 'object' && error !== null && 'code' in error && error.code === '23505';
|
|
88
|
-
}
|
|
89
123
|
//# sourceMappingURL=developer-grant-store-postgres.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"developer-grant-store-postgres.js","sourceRoot":"","sources":["../../src/oauth/developer-grant-store-postgres.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAEpE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,
|
|
1
|
+
{"version":3,"file":"developer-grant-store-postgres.js","sourceRoot":"","sources":["../../src/oauth/developer-grant-store-postgres.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { type DeveloperCapability } from '@noodle-borg/developer-mcp';
|
|
2
|
+
export declare const DEVELOPER_GRANT_VERSION: 2;
|
|
3
|
+
export declare const DEVELOPER_GRANT_ACCESS_MODEL: "live_user";
|
|
2
4
|
export interface DeveloperAccessGrant {
|
|
5
|
+
readonly version: typeof DEVELOPER_GRANT_VERSION;
|
|
3
6
|
readonly id: string;
|
|
4
7
|
readonly clientId: string;
|
|
5
8
|
readonly subject: string;
|
|
6
|
-
readonly
|
|
7
|
-
readonly
|
|
9
|
+
readonly resource: string;
|
|
10
|
+
readonly accessModel: typeof DEVELOPER_GRANT_ACCESS_MODEL;
|
|
8
11
|
readonly capabilities: readonly DeveloperCapability[];
|
|
9
12
|
readonly createdAt: string;
|
|
10
13
|
readonly updatedAt: string;
|
|
@@ -14,19 +17,26 @@ export interface DeveloperAccessGrant {
|
|
|
14
17
|
export interface CreateDeveloperAccessGrant {
|
|
15
18
|
readonly clientId: string;
|
|
16
19
|
readonly subject: string;
|
|
17
|
-
readonly
|
|
18
|
-
readonly environments: readonly string[];
|
|
20
|
+
readonly resource: string;
|
|
19
21
|
readonly capabilities: readonly DeveloperCapability[];
|
|
20
22
|
readonly expiresAt?: string;
|
|
21
23
|
}
|
|
24
|
+
export interface ActiveDeveloperGrantLookup {
|
|
25
|
+
readonly clientId: string;
|
|
26
|
+
readonly subject: string;
|
|
27
|
+
readonly resource: string;
|
|
28
|
+
readonly at?: string;
|
|
29
|
+
}
|
|
22
30
|
export interface DeveloperGrantStore {
|
|
23
|
-
|
|
31
|
+
getOrCreateActive(input: CreateDeveloperAccessGrant): Promise<DeveloperAccessGrant>;
|
|
32
|
+
getActive(input: ActiveDeveloperGrantLookup): Promise<DeveloperAccessGrant | undefined>;
|
|
24
33
|
get(id: string): Promise<DeveloperAccessGrant | undefined>;
|
|
25
34
|
revoke(id: string, at: string): Promise<DeveloperAccessGrant | undefined>;
|
|
26
35
|
}
|
|
27
36
|
export interface ActiveDeveloperGrantInput {
|
|
28
37
|
readonly subject: string;
|
|
29
38
|
readonly clientId: string;
|
|
39
|
+
readonly resource: string;
|
|
30
40
|
readonly at: string;
|
|
31
41
|
}
|
|
32
42
|
export interface DeveloperGrantFactoryOptions {
|
|
@@ -37,7 +47,8 @@ export type InMemoryDeveloperGrantStoreOptions = DeveloperGrantFactoryOptions;
|
|
|
37
47
|
export declare class InMemoryDeveloperGrantStore implements DeveloperGrantStore {
|
|
38
48
|
#private;
|
|
39
49
|
constructor(options?: InMemoryDeveloperGrantStoreOptions);
|
|
40
|
-
|
|
50
|
+
getOrCreateActive(input: CreateDeveloperAccessGrant): Promise<DeveloperAccessGrant>;
|
|
51
|
+
getActive(input: ActiveDeveloperGrantLookup): Promise<DeveloperAccessGrant | undefined>;
|
|
41
52
|
get(id: string): Promise<DeveloperAccessGrant | undefined>;
|
|
42
53
|
revoke(id: string, at: string): Promise<DeveloperAccessGrant | undefined>;
|
|
43
54
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"developer-grant.d.ts","sourceRoot":"","sources":["../../src/oauth/developer-grant.ts"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"developer-grant.d.ts","sourceRoot":"","sources":["../../src/oauth/developer-grant.ts"],"names":[],"mappings":"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"}
|