@girardmedia/bootspring 2.1.3 → 2.2.1
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/bin/bootspring.js +157 -83
- package/claude-commands/agent.md +34 -0
- package/claude-commands/bs.md +31 -0
- package/claude-commands/build.md +25 -0
- package/claude-commands/skill.md +31 -0
- package/claude-commands/todo.md +25 -0
- package/dist/core/index.d.ts +5814 -0
- package/dist/core.js +5779 -0
- package/dist/index.js +93883 -0
- package/dist/mcp/index.d.ts +1 -0
- package/dist/mcp-server.js +2298 -0
- package/generators/api-docs.js +3 -3
- package/generators/decisions.js +14 -14
- package/generators/health.js +6 -6
- package/generators/sprint.js +4 -4
- package/generators/templates/build-planning.template.js +2 -2
- package/generators/visual-doc-generator.js +1 -1
- package/package.json +22 -68
- package/cli/agent.js +0 -799
- package/cli/auth.js +0 -896
- package/cli/billing.js +0 -320
- package/cli/build.js +0 -1442
- package/cli/dashboard.js +0 -123
- package/cli/init.js +0 -669
- package/cli/mcp.js +0 -240
- package/cli/orchestrator.js +0 -240
- package/cli/project.js +0 -825
- package/cli/quality.js +0 -281
- package/cli/skill.js +0 -503
- package/cli/switch.js +0 -453
- package/cli/todo.js +0 -629
- package/cli/update.js +0 -132
- package/core/api-client.d.ts +0 -69
- package/core/api-client.js +0 -1482
- package/core/auth.d.ts +0 -98
- package/core/auth.js +0 -737
- package/core/build-orchestrator.js +0 -508
- package/core/build-state.js +0 -612
- package/core/config.d.ts +0 -106
- package/core/config.js +0 -1328
- package/core/context-loader.js +0 -580
- package/core/context.d.ts +0 -61
- package/core/context.js +0 -327
- package/core/entitlements.d.ts +0 -70
- package/core/entitlements.js +0 -322
- package/core/index.d.ts +0 -53
- package/core/index.js +0 -62
- package/core/mcp-config.js +0 -115
- package/core/policies.d.ts +0 -43
- package/core/policies.js +0 -113
- package/core/policy-matrix.js +0 -303
- package/core/project-activity.js +0 -175
- package/core/redaction.d.ts +0 -5
- package/core/redaction.js +0 -63
- package/core/self-update.js +0 -259
- package/core/session.js +0 -353
- package/core/task-extractor.js +0 -1098
- package/core/telemetry.d.ts +0 -55
- package/core/telemetry.js +0 -617
- package/core/tier-enforcement.js +0 -928
- package/core/utils.d.ts +0 -90
- package/core/utils.js +0 -455
- package/core/validation.js +0 -572
- package/mcp/server.d.ts +0 -57
- package/mcp/server.js +0 -264
package/core/index.d.ts
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Bootspring Core TypeScript Declarations
|
|
3
|
-
* @package @girardmedia/bootspring
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import * as config from './config';
|
|
7
|
-
import * as context from './context';
|
|
8
|
-
import * as utils from './utils';
|
|
9
|
-
import * as policies from './policies';
|
|
10
|
-
import * as entitlements from './entitlements';
|
|
11
|
-
import * as telemetry from './telemetry';
|
|
12
|
-
import * as auth from './auth';
|
|
13
|
-
import * as api from './api-client';
|
|
14
|
-
import * as redaction from './redaction';
|
|
15
|
-
|
|
16
|
-
/** Current package version */
|
|
17
|
-
export const VERSION: string;
|
|
18
|
-
|
|
19
|
-
/** Core modules */
|
|
20
|
-
export { config, context, utils, policies, entitlements, telemetry, auth, api, redaction };
|
|
21
|
-
|
|
22
|
-
/** Load configuration from bootspring.config.js */
|
|
23
|
-
export const loadConfig: typeof config.load;
|
|
24
|
-
|
|
25
|
-
/** Get project context */
|
|
26
|
-
export const getContext: typeof context.get;
|
|
27
|
-
|
|
28
|
-
/** Validate project context */
|
|
29
|
-
export const validateContext: typeof context.validate;
|
|
30
|
-
|
|
31
|
-
/** Check if user has access to a skill */
|
|
32
|
-
export const checkSkillAccess: typeof entitlements.checkSkillAccess;
|
|
33
|
-
|
|
34
|
-
/** Check if user has access to a workflow */
|
|
35
|
-
export const checkWorkflowAccess: typeof entitlements.checkWorkflowAccess;
|
|
36
|
-
|
|
37
|
-
/** Check if user is authenticated */
|
|
38
|
-
export const isAuthenticated: typeof auth.isAuthenticated;
|
|
39
|
-
|
|
40
|
-
/** Get current user info */
|
|
41
|
-
export const getUser: typeof auth.getUser;
|
|
42
|
-
|
|
43
|
-
/** Get user's subscription tier */
|
|
44
|
-
export const getTier: typeof auth.getTier;
|
|
45
|
-
|
|
46
|
-
/** Brand information */
|
|
47
|
-
export const BRAND: {
|
|
48
|
-
name: 'Bootspring';
|
|
49
|
-
tagline: 'Development scaffolding with intelligence';
|
|
50
|
-
website: 'https://bootspring.com';
|
|
51
|
-
docs: 'https://bootspring.com/docs';
|
|
52
|
-
api: 'https://api.bootspring.com';
|
|
53
|
-
};
|
package/core/index.js
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Bootspring Core
|
|
3
|
-
* Main exports for the Bootspring package
|
|
4
|
-
*
|
|
5
|
-
* @package bootspring
|
|
6
|
-
* @module core
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const config = require('./config');
|
|
10
|
-
const context = require('./context');
|
|
11
|
-
const utils = require('./utils');
|
|
12
|
-
const policies = require('./policies');
|
|
13
|
-
const entitlements = require('./entitlements');
|
|
14
|
-
const tierEnforcement = require('./tier-enforcement');
|
|
15
|
-
const telemetry = require('./telemetry');
|
|
16
|
-
const auth = require('./auth');
|
|
17
|
-
const api = require('./api-client');
|
|
18
|
-
const redaction = require('./redaction');
|
|
19
|
-
const packageJson = require('../package.json');
|
|
20
|
-
|
|
21
|
-
module.exports = {
|
|
22
|
-
// Version
|
|
23
|
-
VERSION: packageJson.version,
|
|
24
|
-
|
|
25
|
-
// Core modules
|
|
26
|
-
config,
|
|
27
|
-
context,
|
|
28
|
-
utils,
|
|
29
|
-
policies,
|
|
30
|
-
entitlements,
|
|
31
|
-
tierEnforcement,
|
|
32
|
-
telemetry,
|
|
33
|
-
auth,
|
|
34
|
-
api,
|
|
35
|
-
redaction,
|
|
36
|
-
|
|
37
|
-
// Convenience exports
|
|
38
|
-
loadConfig: config.load,
|
|
39
|
-
getContext: context.get,
|
|
40
|
-
validateContext: context.validate,
|
|
41
|
-
checkSkillAccess: entitlements.checkSkillAccess,
|
|
42
|
-
checkWorkflowAccess: entitlements.checkWorkflowAccess,
|
|
43
|
-
|
|
44
|
-
// Tier enforcement convenience exports
|
|
45
|
-
getTier: tierEnforcement.getTier,
|
|
46
|
-
checkAgentAccess: tierEnforcement.checkAgentAccess,
|
|
47
|
-
hasFeature: tierEnforcement.hasFeature,
|
|
48
|
-
meetsTierRequirement: tierEnforcement.meetsTierRequirement,
|
|
49
|
-
|
|
50
|
-
// Auth convenience exports
|
|
51
|
-
isAuthenticated: auth.isAuthenticated,
|
|
52
|
-
getUser: auth.getUser,
|
|
53
|
-
|
|
54
|
-
// Brand info
|
|
55
|
-
BRAND: {
|
|
56
|
-
name: 'Bootspring',
|
|
57
|
-
tagline: 'Development scaffolding with intelligence',
|
|
58
|
-
website: 'https://bootspring.com',
|
|
59
|
-
docs: 'https://bootspring.com/docs',
|
|
60
|
-
api: 'https://api.bootspring.com'
|
|
61
|
-
}
|
|
62
|
-
};
|
package/core/mcp-config.js
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
|
|
4
|
-
const PACKAGE_NAME = require('../package.json').name || '@girardmedia/bootspring';
|
|
5
|
-
const PROJECT_MCP_FILENAME = '.mcp.json';
|
|
6
|
-
|
|
7
|
-
function getManagedMcpServerConfig() {
|
|
8
|
-
return {
|
|
9
|
-
command: 'npx',
|
|
10
|
-
args: ['-y', PACKAGE_NAME, 'mcp'],
|
|
11
|
-
env: {}
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function isManagedMcpServerConfig(serverConfig) {
|
|
16
|
-
const expected = getManagedMcpServerConfig();
|
|
17
|
-
return (
|
|
18
|
-
serverConfig?.command === expected.command &&
|
|
19
|
-
Array.isArray(serverConfig?.args) &&
|
|
20
|
-
serverConfig.args.join('\u0000') === expected.args.join('\u0000')
|
|
21
|
-
);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function normalizeManagedMcpServerConfig(existingServerConfig) {
|
|
25
|
-
const managedConfig = getManagedMcpServerConfig();
|
|
26
|
-
const env = existingServerConfig?.env && typeof existingServerConfig.env === 'object' && !Array.isArray(existingServerConfig.env)
|
|
27
|
-
? existingServerConfig.env
|
|
28
|
-
: {};
|
|
29
|
-
|
|
30
|
-
return {
|
|
31
|
-
...managedConfig,
|
|
32
|
-
env
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function ensureProjectMcpConfig(projectRoot = process.cwd(), options = {}) {
|
|
37
|
-
const createIfMissing = options.createIfMissing === true;
|
|
38
|
-
const mcpPath = path.join(projectRoot, PROJECT_MCP_FILENAME);
|
|
39
|
-
|
|
40
|
-
if (!fs.existsSync(mcpPath)) {
|
|
41
|
-
if (!createIfMissing) {
|
|
42
|
-
return { status: 'missing', changed: false, path: mcpPath };
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const nextConfig = {
|
|
46
|
-
mcpServers: {
|
|
47
|
-
bootspring: getManagedMcpServerConfig()
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
fs.writeFileSync(mcpPath, JSON.stringify(nextConfig, null, 2));
|
|
53
|
-
return { status: 'created', changed: true, path: mcpPath, config: nextConfig };
|
|
54
|
-
} catch (error) {
|
|
55
|
-
return { status: 'error', changed: false, path: mcpPath, error };
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
let currentConfig;
|
|
60
|
-
try {
|
|
61
|
-
currentConfig = JSON.parse(fs.readFileSync(mcpPath, 'utf8'));
|
|
62
|
-
} catch (error) {
|
|
63
|
-
return { status: 'invalid', changed: false, path: mcpPath, error };
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (!currentConfig || typeof currentConfig !== 'object' || Array.isArray(currentConfig)) {
|
|
67
|
-
return {
|
|
68
|
-
status: 'invalid',
|
|
69
|
-
changed: false,
|
|
70
|
-
path: mcpPath,
|
|
71
|
-
error: new Error('Project MCP config must be a JSON object')
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const currentServers = currentConfig.mcpServers && typeof currentConfig.mcpServers === 'object' && !Array.isArray(currentConfig.mcpServers)
|
|
76
|
-
? currentConfig.mcpServers
|
|
77
|
-
: {};
|
|
78
|
-
const currentBootspring = currentServers.bootspring;
|
|
79
|
-
|
|
80
|
-
if (currentBootspring && isManagedMcpServerConfig(currentBootspring)) {
|
|
81
|
-
return { status: 'unchanged', changed: false, path: mcpPath, config: currentConfig };
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (!currentBootspring && !createIfMissing) {
|
|
85
|
-
return { status: 'absent', changed: false, path: mcpPath, config: currentConfig };
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const nextConfig = {
|
|
89
|
-
...currentConfig,
|
|
90
|
-
mcpServers: {
|
|
91
|
-
...currentServers,
|
|
92
|
-
bootspring: normalizeManagedMcpServerConfig(currentBootspring)
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
try {
|
|
97
|
-
fs.writeFileSync(mcpPath, JSON.stringify(nextConfig, null, 2));
|
|
98
|
-
return {
|
|
99
|
-
status: currentBootspring ? 'updated' : 'added',
|
|
100
|
-
changed: true,
|
|
101
|
-
path: mcpPath,
|
|
102
|
-
config: nextConfig
|
|
103
|
-
};
|
|
104
|
-
} catch (error) {
|
|
105
|
-
return { status: 'error', changed: false, path: mcpPath, error };
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
module.exports = {
|
|
110
|
-
PACKAGE_NAME,
|
|
111
|
-
PROJECT_MCP_FILENAME,
|
|
112
|
-
getManagedMcpServerConfig,
|
|
113
|
-
isManagedMcpServerConfig,
|
|
114
|
-
ensureProjectMcpConfig
|
|
115
|
-
};
|
package/core/policies.d.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Bootspring Policies Types
|
|
3
|
-
* @module core/policies
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export type PolicyProfile = 'startup' | 'regulated' | 'enterprise';
|
|
7
|
-
|
|
8
|
-
export interface Policy {
|
|
9
|
-
profile: PolicyProfile;
|
|
10
|
-
blockedWorkflows: string[];
|
|
11
|
-
blockedSkills: string[];
|
|
12
|
-
requireApproval: string[];
|
|
13
|
-
auditLevel: 'none' | 'basic' | 'full';
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Get policy for current environment
|
|
18
|
-
* @param profile - Optional profile override
|
|
19
|
-
* @returns Policy configuration
|
|
20
|
-
*/
|
|
21
|
-
export function getPolicy(profile?: PolicyProfile): Policy;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Check if workflow is allowed by policy
|
|
25
|
-
* @param workflowId - Workflow identifier
|
|
26
|
-
* @param policy - Optional policy to check against
|
|
27
|
-
* @returns True if allowed
|
|
28
|
-
*/
|
|
29
|
-
export function isWorkflowAllowed(workflowId: string, policy?: Policy): boolean;
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Check if skill is allowed by policy
|
|
33
|
-
* @param skillId - Skill identifier
|
|
34
|
-
* @param policy - Optional policy to check against
|
|
35
|
-
* @returns True if allowed
|
|
36
|
-
*/
|
|
37
|
-
export function isSkillAllowed(skillId: string, policy?: Policy): boolean;
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Resolve policy profile from environment
|
|
41
|
-
* @returns Current policy profile
|
|
42
|
-
*/
|
|
43
|
-
export function resolveProfile(): PolicyProfile;
|
package/core/policies.js
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Bootspring policy profiles
|
|
3
|
-
* Team-level and org-level controls for capability gating.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const policyMatrix = require('./policy-matrix');
|
|
7
|
-
|
|
8
|
-
const DEFAULT_POLICY_PROFILE = 'startup';
|
|
9
|
-
|
|
10
|
-
const POLICY_PROFILES = {
|
|
11
|
-
startup: {
|
|
12
|
-
id: 'startup',
|
|
13
|
-
name: 'Startup',
|
|
14
|
-
description: 'Permissive policy for fast iteration',
|
|
15
|
-
allowExternalSkills: true,
|
|
16
|
-
blockedWorkflows: [],
|
|
17
|
-
tier: 'any'
|
|
18
|
-
},
|
|
19
|
-
regulated: {
|
|
20
|
-
id: 'regulated',
|
|
21
|
-
name: 'Regulated',
|
|
22
|
-
description: 'Compliance-focused with external skill restrictions',
|
|
23
|
-
allowExternalSkills: false,
|
|
24
|
-
blockedWorkflows: ['growth-pack'],
|
|
25
|
-
tier: 'team'
|
|
26
|
-
},
|
|
27
|
-
enterprise: {
|
|
28
|
-
id: 'enterprise',
|
|
29
|
-
name: 'Enterprise',
|
|
30
|
-
description: 'Full control with SSO and audit requirements',
|
|
31
|
-
allowExternalSkills: true,
|
|
32
|
-
blockedWorkflows: [],
|
|
33
|
-
tier: 'enterprise'
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
function normalizeProfile(profile) {
|
|
38
|
-
const key = String(profile || DEFAULT_POLICY_PROFILE).trim().toLowerCase();
|
|
39
|
-
return POLICY_PROFILES[key] ? key : DEFAULT_POLICY_PROFILE;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function parseCsvList(value) {
|
|
43
|
-
if (!value) return [];
|
|
44
|
-
return String(value)
|
|
45
|
-
.split(',')
|
|
46
|
-
.map(item => item.trim())
|
|
47
|
-
.filter(Boolean);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function resolvePolicyProfile(options = {}) {
|
|
51
|
-
return normalizeProfile(options.policyProfile || process.env.BOOTSPRING_POLICY_PROFILE);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function getPolicyProfile(profile, options = {}) {
|
|
55
|
-
const key = normalizeProfile(profile);
|
|
56
|
-
const base = POLICY_PROFILES[key];
|
|
57
|
-
const blockedFromEnv = parseCsvList(options.blockedWorkflows || process.env.BOOTSPRING_POLICY_BLOCKED_WORKFLOWS);
|
|
58
|
-
return {
|
|
59
|
-
...base,
|
|
60
|
-
blockedWorkflows: Array.from(new Set([...(base.blockedWorkflows || []), ...blockedFromEnv]))
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function isWorkflowBlocked(workflow, profile) {
|
|
65
|
-
const workflowKey = String(workflow?.key || workflow || '').trim();
|
|
66
|
-
if (!workflowKey) return false;
|
|
67
|
-
return (profile.blockedWorkflows || []).includes(workflowKey);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Check if a scope is blocked by policy
|
|
72
|
-
* @param {string} scope - Scope to check (e.g., 'skills.external')
|
|
73
|
-
* @param {string} tier - Current tier
|
|
74
|
-
* @param {string} profile - Policy profile
|
|
75
|
-
* @param {object} memberOverrides - Per-member overrides
|
|
76
|
-
* @returns {object} Access result
|
|
77
|
-
*/
|
|
78
|
-
function checkScopeAccess(scope, tier = 'free', profile = 'startup', memberOverrides = {}) {
|
|
79
|
-
const effectivePolicy = policyMatrix.buildEffectivePolicy(tier, profile, memberOverrides);
|
|
80
|
-
return policyMatrix.checkPolicyAccess(scope, effectivePolicy);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Get all available policy profiles
|
|
85
|
-
* @returns {object[]} List of profiles
|
|
86
|
-
*/
|
|
87
|
-
function listPolicyProfiles() {
|
|
88
|
-
return Object.values(POLICY_PROFILES).map(p => ({
|
|
89
|
-
id: p.id,
|
|
90
|
-
name: p.name,
|
|
91
|
-
description: p.description,
|
|
92
|
-
tier: p.tier
|
|
93
|
-
}));
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Get policy scopes
|
|
98
|
-
* @returns {object} Available scopes
|
|
99
|
-
*/
|
|
100
|
-
function getPolicyScopes() {
|
|
101
|
-
return policyMatrix.POLICY_SCOPES;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
module.exports = {
|
|
105
|
-
DEFAULT_POLICY_PROFILE,
|
|
106
|
-
POLICY_PROFILES,
|
|
107
|
-
resolvePolicyProfile,
|
|
108
|
-
getPolicyProfile,
|
|
109
|
-
isWorkflowBlocked,
|
|
110
|
-
checkScopeAccess,
|
|
111
|
-
listPolicyProfiles,
|
|
112
|
-
getPolicyScopes
|
|
113
|
-
};
|
package/core/policy-matrix.js
DELETED
|
@@ -1,303 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Policy Matrix
|
|
3
|
-
* Comprehensive policy definitions for org-level gates
|
|
4
|
-
* @package bootspring
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Policy scopes define what can be controlled
|
|
9
|
-
*/
|
|
10
|
-
const POLICY_SCOPES = {
|
|
11
|
-
skills: {
|
|
12
|
-
external: 'skills.external', // Third-party/external skills
|
|
13
|
-
premium: 'skills.premium', // Premium skill categories
|
|
14
|
-
ai: 'skills.ai', // AI-powered skills
|
|
15
|
-
all: 'skills.*'
|
|
16
|
-
},
|
|
17
|
-
workflows: {
|
|
18
|
-
parallel: 'workflows.parallel', // Parallel execution
|
|
19
|
-
premium: 'workflows.premium', // Premium workflow packs
|
|
20
|
-
custom: 'workflows.custom', // Custom workflow definitions
|
|
21
|
-
all: 'workflows.*'
|
|
22
|
-
},
|
|
23
|
-
agents: {
|
|
24
|
-
technical: 'agents.technical', // Technical experts
|
|
25
|
-
business: 'agents.business', // Business/legal experts
|
|
26
|
-
enterprise: 'agents.enterprise', // Enterprise-only agents
|
|
27
|
-
all: 'agents.*'
|
|
28
|
-
},
|
|
29
|
-
features: {
|
|
30
|
-
telemetry: 'features.telemetry', // Usage telemetry
|
|
31
|
-
cloudSync: 'features.cloud_sync', // Cloud synchronization
|
|
32
|
-
teamSharing: 'features.team_sharing', // Team context sharing
|
|
33
|
-
auditLogs: 'features.audit_logs', // Audit logging
|
|
34
|
-
apiAccess: 'features.api_access', // Direct API access
|
|
35
|
-
all: 'features.*'
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Default policy matrix by tier
|
|
41
|
-
* Defines what's allowed/blocked per tier
|
|
42
|
-
*/
|
|
43
|
-
const TIER_POLICY_DEFAULTS = {
|
|
44
|
-
free: {
|
|
45
|
-
allowed: [
|
|
46
|
-
'skills.external',
|
|
47
|
-
'agents.technical',
|
|
48
|
-
'features.telemetry'
|
|
49
|
-
],
|
|
50
|
-
blocked: [
|
|
51
|
-
'skills.premium',
|
|
52
|
-
'skills.ai',
|
|
53
|
-
'workflows.premium',
|
|
54
|
-
'workflows.parallel',
|
|
55
|
-
'agents.business',
|
|
56
|
-
'agents.enterprise',
|
|
57
|
-
'features.cloud_sync',
|
|
58
|
-
'features.team_sharing',
|
|
59
|
-
'features.audit_logs'
|
|
60
|
-
],
|
|
61
|
-
limits: {
|
|
62
|
-
skillsPerDay: 50,
|
|
63
|
-
workflowsPerDay: 10,
|
|
64
|
-
agentInvocationsPerDay: 20
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
pro: {
|
|
68
|
-
allowed: [
|
|
69
|
-
'skills.*',
|
|
70
|
-
'workflows.*',
|
|
71
|
-
'agents.technical',
|
|
72
|
-
'agents.business',
|
|
73
|
-
'features.telemetry',
|
|
74
|
-
'features.cloud_sync'
|
|
75
|
-
],
|
|
76
|
-
blocked: [
|
|
77
|
-
'agents.enterprise',
|
|
78
|
-
'features.team_sharing',
|
|
79
|
-
'features.audit_logs'
|
|
80
|
-
],
|
|
81
|
-
limits: {
|
|
82
|
-
skillsPerDay: 500,
|
|
83
|
-
workflowsPerDay: 100,
|
|
84
|
-
agentInvocationsPerDay: 200
|
|
85
|
-
}
|
|
86
|
-
},
|
|
87
|
-
team: {
|
|
88
|
-
allowed: [
|
|
89
|
-
'skills.*',
|
|
90
|
-
'workflows.*',
|
|
91
|
-
'agents.*',
|
|
92
|
-
'features.telemetry',
|
|
93
|
-
'features.cloud_sync',
|
|
94
|
-
'features.team_sharing',
|
|
95
|
-
'features.audit_logs'
|
|
96
|
-
],
|
|
97
|
-
blocked: [],
|
|
98
|
-
limits: {
|
|
99
|
-
skillsPerDay: 2000,
|
|
100
|
-
workflowsPerDay: 500,
|
|
101
|
-
agentInvocationsPerDay: 1000,
|
|
102
|
-
teamMembers: 10
|
|
103
|
-
}
|
|
104
|
-
},
|
|
105
|
-
enterprise: {
|
|
106
|
-
allowed: ['*'],
|
|
107
|
-
blocked: [],
|
|
108
|
-
limits: {
|
|
109
|
-
skillsPerDay: -1, // Unlimited
|
|
110
|
-
workflowsPerDay: -1,
|
|
111
|
-
agentInvocationsPerDay: -1,
|
|
112
|
-
teamMembers: -1
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Profile-specific policy overrides
|
|
119
|
-
* Applied on top of tier defaults
|
|
120
|
-
*/
|
|
121
|
-
const PROFILE_OVERRIDES = {
|
|
122
|
-
startup: {
|
|
123
|
-
// Startup profile: permissive, fast iteration
|
|
124
|
-
overrides: {},
|
|
125
|
-
additionalBlocked: []
|
|
126
|
-
},
|
|
127
|
-
regulated: {
|
|
128
|
-
// Regulated profile: compliance-focused
|
|
129
|
-
overrides: {
|
|
130
|
-
requireApproval: ['workflows.custom', 'skills.external'],
|
|
131
|
-
auditAll: true,
|
|
132
|
-
dataResidency: true
|
|
133
|
-
},
|
|
134
|
-
additionalBlocked: [
|
|
135
|
-
'skills.external',
|
|
136
|
-
'workflows.growth-pack'
|
|
137
|
-
]
|
|
138
|
-
},
|
|
139
|
-
enterprise: {
|
|
140
|
-
// Enterprise profile: full control
|
|
141
|
-
overrides: {
|
|
142
|
-
ssoRequired: true,
|
|
143
|
-
auditAll: true,
|
|
144
|
-
approvalWorkflow: true
|
|
145
|
-
},
|
|
146
|
-
additionalBlocked: []
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Member role permissions
|
|
152
|
-
* What each role can do within an org
|
|
153
|
-
*/
|
|
154
|
-
const ROLE_PERMISSIONS = {
|
|
155
|
-
owner: {
|
|
156
|
-
canManageOrg: true,
|
|
157
|
-
canManageMembers: true,
|
|
158
|
-
canManagePolicies: true,
|
|
159
|
-
canManageBilling: true,
|
|
160
|
-
canUseAllFeatures: true
|
|
161
|
-
},
|
|
162
|
-
admin: {
|
|
163
|
-
canManageOrg: false,
|
|
164
|
-
canManageMembers: true,
|
|
165
|
-
canManagePolicies: true,
|
|
166
|
-
canManageBilling: false,
|
|
167
|
-
canUseAllFeatures: true
|
|
168
|
-
},
|
|
169
|
-
member: {
|
|
170
|
-
canManageOrg: false,
|
|
171
|
-
canManageMembers: false,
|
|
172
|
-
canManagePolicies: false,
|
|
173
|
-
canManageBilling: false,
|
|
174
|
-
canUseAllFeatures: true
|
|
175
|
-
},
|
|
176
|
-
viewer: {
|
|
177
|
-
canManageOrg: false,
|
|
178
|
-
canManageMembers: false,
|
|
179
|
-
canManagePolicies: false,
|
|
180
|
-
canManageBilling: false,
|
|
181
|
-
canUseAllFeatures: false
|
|
182
|
-
}
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Check if a scope matches a pattern
|
|
187
|
-
* @param {string} scope - Specific scope (e.g., 'skills.external')
|
|
188
|
-
* @param {string} pattern - Pattern to match (e.g., 'skills.*' or 'skills.external')
|
|
189
|
-
* @returns {boolean}
|
|
190
|
-
*/
|
|
191
|
-
function matchesScope(scope, pattern) {
|
|
192
|
-
if (pattern === '*') return true;
|
|
193
|
-
if (pattern === scope) return true;
|
|
194
|
-
if (pattern.endsWith('.*')) {
|
|
195
|
-
const prefix = pattern.slice(0, -2);
|
|
196
|
-
return scope.startsWith(prefix + '.');
|
|
197
|
-
}
|
|
198
|
-
return false;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Check if a scope is allowed by policy
|
|
203
|
-
* @param {string} scope - Scope to check
|
|
204
|
-
* @param {string[]} allowed - Allowed patterns
|
|
205
|
-
* @param {string[]} blocked - Blocked patterns
|
|
206
|
-
* @returns {boolean}
|
|
207
|
-
*/
|
|
208
|
-
function isScopeAllowed(scope, allowed, blocked) {
|
|
209
|
-
// Check blocked first (blocked takes precedence)
|
|
210
|
-
for (const pattern of blocked) {
|
|
211
|
-
if (matchesScope(scope, pattern)) {
|
|
212
|
-
return false;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
// Check allowed
|
|
216
|
-
for (const pattern of allowed) {
|
|
217
|
-
if (matchesScope(scope, pattern)) {
|
|
218
|
-
return true;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
return false;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Build effective policy for an org member
|
|
226
|
-
* @param {string} tier - Org tier (free/pro/team/enterprise)
|
|
227
|
-
* @param {string} profile - Policy profile (startup/regulated/enterprise)
|
|
228
|
-
* @param {object} memberOverrides - Per-member policy overrides
|
|
229
|
-
* @returns {object} Effective policy
|
|
230
|
-
*/
|
|
231
|
-
function buildEffectivePolicy(tier, profile, memberOverrides = {}) {
|
|
232
|
-
const tierDefaults = TIER_POLICY_DEFAULTS[tier] || TIER_POLICY_DEFAULTS.free;
|
|
233
|
-
const profileOverrides = PROFILE_OVERRIDES[profile] || PROFILE_OVERRIDES.startup;
|
|
234
|
-
|
|
235
|
-
// Merge allowed/blocked lists
|
|
236
|
-
const allowed = [...tierDefaults.allowed];
|
|
237
|
-
const blocked = [
|
|
238
|
-
...tierDefaults.blocked,
|
|
239
|
-
...profileOverrides.additionalBlocked
|
|
240
|
-
];
|
|
241
|
-
|
|
242
|
-
// Apply member overrides
|
|
243
|
-
if (memberOverrides.additionalAllowed) {
|
|
244
|
-
allowed.push(...memberOverrides.additionalAllowed);
|
|
245
|
-
}
|
|
246
|
-
if (memberOverrides.additionalBlocked) {
|
|
247
|
-
blocked.push(...memberOverrides.additionalBlocked);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
return {
|
|
251
|
-
tier,
|
|
252
|
-
profile,
|
|
253
|
-
allowed: [...new Set(allowed)],
|
|
254
|
-
blocked: [...new Set(blocked)],
|
|
255
|
-
limits: { ...tierDefaults.limits, ...(memberOverrides.limits || {}) },
|
|
256
|
-
overrides: { ...profileOverrides.overrides, ...(memberOverrides.overrides || {}) }
|
|
257
|
-
};
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* Check access against effective policy
|
|
262
|
-
* @param {string} scope - Scope to check
|
|
263
|
-
* @param {object} policy - Effective policy
|
|
264
|
-
* @returns {object} Access result
|
|
265
|
-
*/
|
|
266
|
-
function checkPolicyAccess(scope, policy) {
|
|
267
|
-
const allowed = isScopeAllowed(scope, policy.allowed, policy.blocked);
|
|
268
|
-
|
|
269
|
-
if (!allowed) {
|
|
270
|
-
return {
|
|
271
|
-
allowed: false,
|
|
272
|
-
code: 'policy_blocked',
|
|
273
|
-
scope,
|
|
274
|
-
reason: `Scope "${scope}" is blocked by ${policy.profile} policy`
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
// Check if approval is required
|
|
279
|
-
if (policy.overrides.requireApproval?.some(p => matchesScope(scope, p))) {
|
|
280
|
-
return {
|
|
281
|
-
allowed: true,
|
|
282
|
-
requiresApproval: true,
|
|
283
|
-
scope,
|
|
284
|
-
reason: `Scope "${scope}" requires approval under ${policy.profile} policy`
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
return {
|
|
289
|
-
allowed: true,
|
|
290
|
-
scope
|
|
291
|
-
};
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
module.exports = {
|
|
295
|
-
POLICY_SCOPES,
|
|
296
|
-
TIER_POLICY_DEFAULTS,
|
|
297
|
-
PROFILE_OVERRIDES,
|
|
298
|
-
ROLE_PERMISSIONS,
|
|
299
|
-
matchesScope,
|
|
300
|
-
isScopeAllowed,
|
|
301
|
-
buildEffectivePolicy,
|
|
302
|
-
checkPolicyAccess
|
|
303
|
-
};
|