asana-gate 0.1.0 → 0.1.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/dist/agent-DZc-5ImE.mjs +0 -2
- package/dist/api-Cd3qXjya.mjs +0 -2
- package/dist/check-bGxfSyj4.mjs +0 -2
- package/dist/classification-CGLGDjUo.mjs +0 -2
- package/dist/cli.mjs +1 -3
- package/dist/commands-BG1kdDd7.mjs +0 -2
- package/dist/config-Cz5cQQ6V.mjs +0 -2
- package/dist/context-CtHiLMEu.mjs +0 -2
- package/dist/evaluate-B3QITkuM.mjs +0 -2
- package/dist/explain-DCu8srlb.mjs +0 -2
- package/dist/identity-BueTsN0P.mjs +0 -2
- package/dist/index.cjs +0 -2
- package/dist/index.d.cts +1 -2
- package/dist/index.d.mts +1 -2
- package/dist/index.mjs +0 -2
- package/dist/init-BxNrskT1.mjs +0 -2
- package/dist/listing-cache-DNPtaekS.mjs +0 -2
- package/dist/mcp-DwzrJ0jR.mjs +0 -2
- package/dist/objects-Bs6oIPKt.mjs +0 -2
- package/dist/policy-BsO51rPw.mjs +0 -2
- package/dist/run-Bd7MACE5.mjs +0 -2
- package/dist/session-Bm78YM5P.mjs +0 -2
- package/dist/token-CpUi1ReO.mjs +0 -2
- package/dist/token-command-BBRNF06S.mjs +0 -2
- package/dist/tools-CrftiOhp.mjs +0 -2
- package/package.json +2 -2
- package/skills/asana-gate/SKILL.md +1 -1
- package/skills/asana-gate/references/cli.md +1 -1
- package/skills/asana-gate/references/mcp.md +1 -1
- package/skills/asana-gate/references/policy.md +1 -1
- package/skills/asana-gate/references/tools.md +1 -1
- package/dist/agent-DZc-5ImE.mjs.map +0 -1
- package/dist/api-Cd3qXjya.mjs.map +0 -1
- package/dist/check-bGxfSyj4.mjs.map +0 -1
- package/dist/classification-CGLGDjUo.mjs.map +0 -1
- package/dist/cli.mjs.map +0 -1
- package/dist/commands-BG1kdDd7.mjs.map +0 -1
- package/dist/config-Cz5cQQ6V.mjs.map +0 -1
- package/dist/context-CtHiLMEu.mjs.map +0 -1
- package/dist/evaluate-B3QITkuM.mjs.map +0 -1
- package/dist/explain-DCu8srlb.mjs.map +0 -1
- package/dist/identity-BueTsN0P.mjs.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts.map +0 -1
- package/dist/index.d.mts.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/init-BxNrskT1.mjs.map +0 -1
- package/dist/listing-cache-DNPtaekS.mjs.map +0 -1
- package/dist/mcp-DwzrJ0jR.mjs.map +0 -1
- package/dist/objects-Bs6oIPKt.mjs.map +0 -1
- package/dist/policy-BsO51rPw.mjs.map +0 -1
- package/dist/run-Bd7MACE5.mjs.map +0 -1
- package/dist/session-Bm78YM5P.mjs.map +0 -1
- package/dist/token-CpUi1ReO.mjs.map +0 -1
- package/dist/token-command-BBRNF06S.mjs.map +0 -1
- package/dist/tools-CrftiOhp.mjs.map +0 -1
package/dist/agent-DZc-5ImE.mjs
CHANGED
|
@@ -331,5 +331,3 @@ async function auditAgentFiles(projectDir, version) {
|
|
|
331
331
|
];
|
|
332
332
|
}
|
|
333
333
|
export { wireAgents as a, policyWarnings as c, refreshSkillCopies as i, agentsNamed as n, auditEnvironment as o, auditAgentFiles as r, auditReferences as s, AGENT_NAMES as t };
|
|
334
|
-
|
|
335
|
-
//# sourceMappingURL=agent-DZc-5ImE.mjs.map
|
package/dist/api-Cd3qXjya.mjs
CHANGED
package/dist/check-bGxfSyj4.mjs
CHANGED
|
@@ -3687,5 +3687,3 @@ function ruleFor(operationId) {
|
|
|
3687
3687
|
return CLASSIFICATION[operationId];
|
|
3688
3688
|
}
|
|
3689
3689
|
export { isHttpMethod as A, forbidden as C, noRoute as D, limitExceeded as E, notFound as O, constraintViolation as S, inAction as T, compileRequirement as _, optionFieldsOf as a, GATE_HELP as b, hasConstraints as c, augmentOptFields as d, pick as f, compileApplication as g, specificityOf as h, dataOf as i, matchRoute as j, fillPath as k, labelOf as l, compileState as m, ruleFor as n, redactObject as o, requestedFields as p, createPlanContext as r, constraintsFor as s, CLASSIFICATION as t, FactsLoader as u, memberResolver as v, forbiddenField as w, GateError as x, optionResolver as y };
|
|
3690
|
-
|
|
3691
|
-
//# sourceMappingURL=classification-CGLGDjUo.mjs.map
|
package/dist/cli.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// package.json
|
|
3
|
-
var version = "0.1.
|
|
3
|
+
var version = "0.1.1";
|
|
4
4
|
// src/cli/main.ts
|
|
5
5
|
/**
|
|
6
6
|
* The commands, each loading its own modules when it runs, so a command does
|
|
@@ -104,5 +104,3 @@ async function main(argv, version) {
|
|
|
104
104
|
// src/cli.ts
|
|
105
105
|
process.exitCode = await main(process.argv.slice(2), version);
|
|
106
106
|
export {};
|
|
107
|
-
|
|
108
|
-
//# sourceMappingURL=cli.mjs.map
|
|
@@ -175,5 +175,3 @@ function commandHelp(command) {
|
|
|
175
175
|
].join("\n");
|
|
176
176
|
}
|
|
177
177
|
export { nounHelp as a, coerce as c, findCommand as i, parseArgsOptions as l, commandHelp as n, nouns as o, commandsOf as r, usageOf as s, COMMANDS as t, readData as u };
|
|
178
|
-
|
|
179
|
-
//# sourceMappingURL=commands-BG1kdDd7.mjs.map
|
package/dist/config-Cz5cQQ6V.mjs
CHANGED
|
@@ -1132,5 +1132,3 @@ function describeError(error) {
|
|
|
1132
1132
|
return messageOf(error);
|
|
1133
1133
|
}
|
|
1134
1134
|
export { envValue as A, statIfPresent as B, LEVELS as C, fileSink as D, createLogger as E, patchedJson as F, isAbsent as G, unwritableFile as H, privateDir as I, isObject as J, messagesOf as K, privateFile as L, exposureOf as M, firstWhere as N, silentLogger as O, isFile as P, messageOf as Q, readIfPresent as R, splitList as S, compareSpecificity as T, ASANA_ERROR_HELP as U, unwritable as V, AsanaApiError as W, parseJsonc as X, parseJson$1 as Y, stringOf as Z, TOKEN_FILE as _, describeError as a, AsanaClient as b, usageRows as c, SETTINGS_SCHEMA_URL as d, DurationSchema as f, PROJECT_DIR as g, POLICY_FILE as h, UsageError as i, errnoOf as j, ensureLine as k, DEFAULTS as l, resolveDateBound as m, GATED_OPTIONS as n, isUsageError as o, durationMs as p, parseErrorEntries as q, TOKEN_OPTIONS as r, loadCliSettings as s, COMMON_OPTIONS as t, policyCandidates as u, parseYaml as v, PolicyError as w, renderQuery as x, validated as y, readdirIfPresent as z };
|
|
1135
|
-
|
|
1136
|
-
//# sourceMappingURL=context-CtHiLMEu.mjs.map
|
|
@@ -179,5 +179,3 @@ function grantedActions(policy) {
|
|
|
179
179
|
return new Set(policy.rules.filter((rule) => rule.effect === "allow").flatMap((rule) => [...rule.actions]));
|
|
180
180
|
}
|
|
181
181
|
export { fieldAllowlist as a, isFilterRule as c, workspaceFacts as d, explainResource as i, isVisible as l, WORKSPACE_BRANCH as n, grantedActions as o, allowedActions as r, isAllowed as s, EMPTY as t, whereMatches as u };
|
|
182
|
-
|
|
183
|
-
//# sourceMappingURL=evaluate-B3QITkuM.mjs.map
|
package/dist/index.cjs
CHANGED
|
@@ -14051,5 +14051,3 @@ exports.serveHttp = serveHttp;
|
|
|
14051
14051
|
exports.serveOverStdio = serveOverStdio;
|
|
14052
14052
|
exports.silentLogger = silentLogger;
|
|
14053
14053
|
exports.workspaceFacts = workspaceFacts;
|
|
14054
|
-
|
|
14055
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/index.d.cts
CHANGED
|
@@ -3966,5 +3966,4 @@ declare function managedDir(env: NodeJS.ProcessEnv): string;
|
|
|
3966
3966
|
* or `home`) is not a project's, so the home directory never is one.
|
|
3967
3967
|
*/
|
|
3968
3968
|
declare function findProjectDir(cwd: string, home?: string): Promise<string | undefined>;
|
|
3969
|
-
export { ALL_ACTIONS, ASANA_API_BASE_URL, type Action, AsanaApiError, AsanaClient, type AsanaClientOptions, type AsanaErrorEntry, AsanaNameResolver, type AsanaRequest, type AsanaResponse, type Branch, CLASSIFICATION, type CompiledRule, type CompiledWhere, type CustomFieldDefinition, type Decision, EXPLICIT_ONLY_ACTIONS, type Explanation, FIELD_VERBS, type Facts, FactsLoader, type FactsLoaderOptions, FileListingCache, Gate, GateError, type GateOptions, type GateRequest, type GateResponse, type HttpMethod, type HttpOptions, type ListingCache, type LoadOptions, type Loaded, type LoadedSettings, type LogLevel, type Logger, type Me, type NameResolver, type OperationId, type OperationRule, type OperationSpec, type Policy, PolicyError, type PolicyFile, PolicyFileSchema, type PolicyRule, type PolicyWhere, RESOURCES, RESOURCE_VERBS, type Reference, type ResolverOptions, type Resource, type RouteMatch, RuleSchema, type ScopeKind, type Serving, type Settings, SettingsError, type SettingsFile, SettingsFileSchema, SettingsSchema, type Verb, WhereSchema, allowedActions, compilePolicy, createAsanaGateServer, createLogger, decide, expandActionPattern, expandActionPatterns, explainResource, fieldAllowlist, findProjectDir, homeDir, isAction, isAllowed, isResource, isVisible, loadPolicyFile, loadSettings, managedDir, matchRoute, parsePolicy, referencesOf, serveHttp, serveOverStdio, silentLogger, workspaceFacts };
|
|
3970
|
-
//# sourceMappingURL=index.d.cts.map
|
|
3969
|
+
export { ALL_ACTIONS, ASANA_API_BASE_URL, type Action, AsanaApiError, AsanaClient, type AsanaClientOptions, type AsanaErrorEntry, AsanaNameResolver, type AsanaRequest, type AsanaResponse, type Branch, CLASSIFICATION, type CompiledRule, type CompiledWhere, type CustomFieldDefinition, type Decision, EXPLICIT_ONLY_ACTIONS, type Explanation, FIELD_VERBS, type Facts, FactsLoader, type FactsLoaderOptions, FileListingCache, Gate, GateError, type GateOptions, type GateRequest, type GateResponse, type HttpMethod, type HttpOptions, type ListingCache, type LoadOptions, type Loaded, type LoadedSettings, type LogLevel, type Logger, type Me, type NameResolver, type OperationId, type OperationRule, type OperationSpec, type Policy, PolicyError, type PolicyFile, PolicyFileSchema, type PolicyRule, type PolicyWhere, RESOURCES, RESOURCE_VERBS, type Reference, type ResolverOptions, type Resource, type RouteMatch, RuleSchema, type ScopeKind, type Serving, type Settings, SettingsError, type SettingsFile, SettingsFileSchema, SettingsSchema, type Verb, WhereSchema, allowedActions, compilePolicy, createAsanaGateServer, createLogger, decide, expandActionPattern, expandActionPatterns, explainResource, fieldAllowlist, findProjectDir, homeDir, isAction, isAllowed, isResource, isVisible, loadPolicyFile, loadSettings, managedDir, matchRoute, parsePolicy, referencesOf, serveHttp, serveOverStdio, silentLogger, workspaceFacts };
|
package/dist/index.d.mts
CHANGED
|
@@ -3966,5 +3966,4 @@ declare function managedDir(env: NodeJS.ProcessEnv): string;
|
|
|
3966
3966
|
* or `home`) is not a project's, so the home directory never is one.
|
|
3967
3967
|
*/
|
|
3968
3968
|
declare function findProjectDir(cwd: string, home?: string): Promise<string | undefined>;
|
|
3969
|
-
export { ALL_ACTIONS, ASANA_API_BASE_URL, type Action, AsanaApiError, AsanaClient, type AsanaClientOptions, type AsanaErrorEntry, AsanaNameResolver, type AsanaRequest, type AsanaResponse, type Branch, CLASSIFICATION, type CompiledRule, type CompiledWhere, type CustomFieldDefinition, type Decision, EXPLICIT_ONLY_ACTIONS, type Explanation, FIELD_VERBS, type Facts, FactsLoader, type FactsLoaderOptions, FileListingCache, Gate, GateError, type GateOptions, type GateRequest, type GateResponse, type HttpMethod, type HttpOptions, type ListingCache, type LoadOptions, type Loaded, type LoadedSettings, type LogLevel, type Logger, type Me, type NameResolver, type OperationId, type OperationRule, type OperationSpec, type Policy, PolicyError, type PolicyFile, PolicyFileSchema, type PolicyRule, type PolicyWhere, RESOURCES, RESOURCE_VERBS, type Reference, type ResolverOptions, type Resource, type RouteMatch, RuleSchema, type ScopeKind, type Serving, type Settings, SettingsError, type SettingsFile, SettingsFileSchema, SettingsSchema, type Verb, WhereSchema, allowedActions, compilePolicy, createAsanaGateServer, createLogger, decide, expandActionPattern, expandActionPatterns, explainResource, fieldAllowlist, findProjectDir, homeDir, isAction, isAllowed, isResource, isVisible, loadPolicyFile, loadSettings, managedDir, matchRoute, parsePolicy, referencesOf, serveHttp, serveOverStdio, silentLogger, workspaceFacts };
|
|
3970
|
-
//# sourceMappingURL=index.d.mts.map
|
|
3969
|
+
export { ALL_ACTIONS, ASANA_API_BASE_URL, type Action, AsanaApiError, AsanaClient, type AsanaClientOptions, type AsanaErrorEntry, AsanaNameResolver, type AsanaRequest, type AsanaResponse, type Branch, CLASSIFICATION, type CompiledRule, type CompiledWhere, type CustomFieldDefinition, type Decision, EXPLICIT_ONLY_ACTIONS, type Explanation, FIELD_VERBS, type Facts, FactsLoader, type FactsLoaderOptions, FileListingCache, Gate, GateError, type GateOptions, type GateRequest, type GateResponse, type HttpMethod, type HttpOptions, type ListingCache, type LoadOptions, type Loaded, type LoadedSettings, type LogLevel, type Logger, type Me, type NameResolver, type OperationId, type OperationRule, type OperationSpec, type Policy, PolicyError, type PolicyFile, PolicyFileSchema, type PolicyRule, type PolicyWhere, RESOURCES, RESOURCE_VERBS, type Reference, type ResolverOptions, type Resource, type RouteMatch, RuleSchema, type ScopeKind, type Serving, type Settings, SettingsError, type SettingsFile, SettingsFileSchema, SettingsSchema, type Verb, WhereSchema, allowedActions, compilePolicy, createAsanaGateServer, createLogger, decide, expandActionPattern, expandActionPatterns, explainResource, fieldAllowlist, findProjectDir, homeDir, isAction, isAllowed, isResource, isVisible, loadPolicyFile, loadSettings, managedDir, matchRoute, parsePolicy, referencesOf, serveHttp, serveOverStdio, silentLogger, workspaceFacts };
|
package/dist/index.mjs
CHANGED
|
@@ -13982,5 +13982,3 @@ async function loadSettings(options) {
|
|
|
13982
13982
|
};
|
|
13983
13983
|
}
|
|
13984
13984
|
export { ALL_ACTIONS, ASANA_API_BASE_URL, AsanaApiError, AsanaClient, AsanaNameResolver, CLASSIFICATION, EXPLICIT_ONLY_ACTIONS, FIELD_VERBS, FactsLoader, FileListingCache, Gate, GateError, OPERATIONS, PolicyError, PolicyFileSchema, RESOURCES, RESOURCE_VERBS, RuleSchema, SettingsError, SettingsFileSchema, SettingsSchema, WhereSchema, allowedActions, compilePolicy, createAsanaGateServer, createLogger, decide, expandActionPattern, expandActionPatterns, explainResource, fieldAllowlist, findProjectDir, homeDir, isAction, isAllowed, isResource, isVisible, loadPolicyFile, loadSettings, managedDir, matchRoute, parsePolicy, referencesOf, serveHttp, serveOverStdio, silentLogger, workspaceFacts };
|
|
13985
|
-
|
|
13986
|
-
//# sourceMappingURL=index.mjs.map
|
package/dist/init-BxNrskT1.mjs
CHANGED
package/dist/mcp-DwzrJ0jR.mjs
CHANGED
|
@@ -4110,5 +4110,3 @@ function resourceOfType(resourceType) {
|
|
|
4110
4110
|
return resourceType !== void 0 && Object.hasOwn(RESOURCE_TYPE_MAP, resourceType) ? RESOURCE_TYPE_MAP[resourceType] : void 0;
|
|
4111
4111
|
}
|
|
4112
4112
|
export { verbOf as C, readActionOf as S, RESOURCE_VERBS as _, resourceOfType as a, isAction as b, POLICY_SCHEMA_URL as c, READ_OPERATIONS as d, objectOperationOf as f, RESOURCES as g, FIELD_VERBS as h, refsOf as i, PolicyFileSchema as l, EXPLICIT_ONLY_ACTIONS as m, gidsOf as n, GidSchema as o, ALL_ACTIONS as p, refOf as r, OPERATOR_KEYS as s, gidOf as t, isGid as u, VERB_TIERS as v, OPERATIONS as w, isResource as x, actionOf as y };
|
|
4113
|
-
|
|
4114
|
-
//# sourceMappingURL=objects-Bs6oIPKt.mjs.map
|
package/dist/policy-BsO51rPw.mjs
CHANGED
package/dist/run-Bd7MACE5.mjs
CHANGED
package/dist/token-CpUi1ReO.mjs
CHANGED
|
@@ -305,5 +305,3 @@ function tokenFileWarning(source) {
|
|
|
305
305
|
return source.file === void 0 ? void 0 : exposureOf(source.file, source.mode);
|
|
306
306
|
}
|
|
307
307
|
export { AsanaNameResolver as a, named as c, tokenText as i, tokenOf as n, collect as o, tokenPlaces as r, matches as s, tokenFileWarning as t };
|
|
308
|
-
|
|
309
|
-
//# sourceMappingURL=token-CpUi1ReO.mjs.map
|
package/dist/tools-CrftiOhp.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "asana-gate",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Declarative access-control policy in front of the Asana API, served to AI agents over MCP.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"access-control",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"@changesets/cli": "^3.0.3",
|
|
59
59
|
"@modelcontextprotocol/client": "^2.4.0",
|
|
60
60
|
"@types/node": "^26.6.6",
|
|
61
|
-
"oxfmt": "^0.
|
|
61
|
+
"oxfmt": "^0.76.0",
|
|
62
62
|
"oxlint": "^1.89.0",
|
|
63
63
|
"oxlint-tsgolint": "^7.0.2004",
|
|
64
64
|
"publint": "^0.3.25",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"agent-DZc-5ImE.mjs","names":[],"sources":["../src/policy/references.ts","../src/cli/audit.ts","../src/cli/agent.ts"],"sourcesContent":["// Copyright 2026 Shinsuke Mori\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { Resource } from \"../catalog/resources.ts\";\nimport type { CompiledWhere, Policy } from \"./types.ts\";\n\n/** One object a policy's scope names by gid (after names were resolved), and where. */\ninterface Reference {\n\treadonly resource: Resource;\n\treadonly gid: string;\n\t/** The rule's index in the policy file. */\n\treadonly rule: number;\n\t/** The `where` member that names it (`project`, `subtree`, …). */\n\treadonly member: string;\n}\n\n/** The `where` members that name objects, the resource each names, and how to read them. */\nconst MEMBERS: readonly {\n\treadonly member: string;\n\treadonly resource: Resource;\n\treadonly of: (where: CompiledWhere) => Iterable<string> | undefined;\n}[] = [\n\t{ member: \"team\", resource: \"team\", of: (where) => where.teams },\n\t{ member: \"portfolio\", resource: \"portfolio\", of: (where) => where.portfolios },\n\t{ member: \"project\", resource: \"project\", of: (where) => where.projects },\n\t{ member: \"section\", resource: \"section\", of: (where) => where.sections },\n\t{ member: \"task\", resource: \"task\", of: (where) => where.tasks },\n\t{ member: \"subtree\", resource: \"task\", of: (where) => where.subtrees },\n\t{ member: \"tag\", resource: \"tag\", of: (where) => where.tags },\n\t{ member: \"assignee\", resource: \"user\", of: (where) => where.assignees },\n\t{ member: \"created_by\", resource: \"user\", of: (where) => where.createdBy },\n\t{\n\t\tmember: \"custom_field\",\n\t\tresource: \"custom_field\",\n\t\tof: (where) => where.customFields?.map((predicate) => predicate.fieldGid),\n\t},\n];\n\n/** Every object the policy's scopes name, once per rule and member (a rule's statements share one scope). */\nfunction referencesOf(policy: Policy): Reference[] {\n\tconst references = new Map<string, Reference>();\n\tfor (const rule of policy.rules) {\n\t\tfor (const { member, resource, of } of MEMBERS) {\n\t\t\tfor (const gid of of(rule.where) ?? []) {\n\t\t\t\treferences.set(`${rule.index}:${member}:${gid}`, {\n\t\t\t\t\tresource,\n\t\t\t\t\tgid,\n\t\t\t\t\trule: rule.index,\n\t\t\t\t\tmember,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\treturn [...references.values()];\n}\n\nexport { referencesOf };\nexport type { Reference };\n","// Copyright 2026 Shinsuke Mori\n// SPDX-License-Identifier: Apache-2.0\n\nimport { EXPLICIT_ONLY_ACTIONS, verbOf } from \"../catalog/resources.ts\";\nimport type { FactsLoader, Loaded } from \"../gate/facts.ts\";\nimport { messageOf } from \"../log.ts\";\nimport { type Branch, grantedActions, isFilterRule } from \"../policy/evaluate.ts\";\nimport { type Reference, referencesOf } from \"../policy/references.ts\";\nimport type { CompiledRule, Policy } from \"../policy/types.ts\";\nimport { exposureOf, statIfPresent, unwritableFile } from \"../system.ts\";\nimport type { CommandContext } from \"./session.ts\";\nimport { tokenFileWarning } from \"./token.ts\";\n\n/** What `check` audits: the policy's claims against Asana, and the environment the gate runs in. */\n\n/** Something `check` found: a problem fails the command, a warning does not. */\ninterface Finding {\n\treadonly level: \"problem\" | \"warning\";\n\treadonly text: string;\n}\n\nconst problem = (text: string): Finding => ({ level: \"problem\", text });\nconst warning = (text: string): Finding => ({ level: \"warning\", text });\n\n/** The rules once each: a file rule compiles to statements that share its index and scope. */\nfunction fileRules(policy: Policy): CompiledRule[] {\n\treturn [...new Map(policy.rules.map((rule) => [rule.index, rule])).values()];\n}\n\n/** Rules that say less than they seem to. */\nfunction policyWarnings(policy: Policy): Finding[] {\n\tconst findings: Finding[] = [];\n\tconst granted = grantedActions(policy);\n\tconst explicit = [...granted].filter((action) => EXPLICIT_ONLY_ACTIONS.has(action));\n\tif (explicit.length > 0) {\n\t\tfindings.push(warning(`explicit-only actions granted: ${explicit.join(\", \")}`));\n\t}\n\tfor (const rule of policy.rules) {\n\t\tif (isFilterRule(rule) && [...rule.actions].some((action) => verbOf(action) === \"read\")) {\n\t\t\tfindings.push(\n\t\t\t\twarning(\n\t\t\t\t\t`rules[${rule.index}] allows read through a tag/assignee/custom_field filter; filters never make objects visible, so that part has no effect`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\tif (granted.size === 0) {\n\t\tfindings.push(warning(\"no rule allows anything; every request will be refused\"));\n\t}\n\tfor (const rule of fileRules(policy)) {\n\t\tfor (const predicate of rule.where.customFields ?? []) {\n\t\t\tfor (const value of predicate.unmatched ?? []) {\n\t\t\t\tfindings.push(\n\t\t\t\t\twarning(\n\t\t\t\t\t\t`rules[${rule.index}].where.custom_field ${predicate.fieldGid}: \"${value}\" is not an option of the field`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\treturn findings;\n}\n\n/** Whether a section sits in one of the projects of the rule naming it (a rule without projects takes any). */\nfunction inRuleProject(policy: Policy, reference: Reference, branches: readonly Branch[]): boolean {\n\tconst projects = policy.rules.find((rule) => rule.index === reference.rule)?.where.projects;\n\treturn (\n\t\tprojects === undefined ||\n\t\tbranches.some((branch) => branch.project !== undefined && projects.has(branch.project))\n\t);\n}\n\n/** Loads one object a scope names; resolves to why it failed when Asana did not answer it. */\nasync function loadOrFailure(\n\tloader: FactsLoader,\n\treference: Reference,\n): Promise<Loaded | undefined | string> {\n\ttry {\n\t\treturn await loader.load(reference.resource, reference.gid);\n\t} catch (error) {\n\t\treturn messageOf(error);\n\t}\n}\n\n/** Loads every object the scopes name and reports the ones that are gone, elsewhere, or misplaced. */\nasync function auditReferences(\n\tpolicy: Policy,\n\tloader: FactsLoader,\n): Promise<{ checked: number; findings: Finding[] }> {\n\tconst references = referencesOf(policy);\n\tconst objects = await Promise.all(\n\t\treferences.map((reference) => loadOrFailure(loader, reference)),\n\t);\n\tconst findings: Finding[] = [];\n\tfor (const [index, reference] of references.entries()) {\n\t\tconst at = `rules[${reference.rule}].where.${reference.member} ${reference.gid}`;\n\t\tconst loaded = objects[index];\n\t\tif (typeof loaded === \"string\") {\n\t\t\tfindings.push(problem(`${at}: could not be checked (${loaded})`));\n\t\t} else if (loaded === undefined) {\n\t\t\tfindings.push(problem(`${at}: not found (deleted, or not visible to this token)`));\n\t\t} else if (reference.resource !== \"user\" && loaded.facts.workspace !== policy.workspace) {\n\t\t\tfindings.push(\n\t\t\t\tproblem(\n\t\t\t\t\t`${at}: in another workspace (${loaded.facts.workspace}), so the rule never applies`,\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (\n\t\t\treference.resource === \"section\" &&\n\t\t\t!inRuleProject(policy, reference, loaded.facts.branches)\n\t\t) {\n\t\t\tfindings.push(\n\t\t\t\tproblem(`${at}: not a section of the rule's project, so the rule never applies`),\n\t\t\t);\n\t\t}\n\t}\n\treturn { checked: references.length, findings };\n}\n\n/** The directories the gate writes to, as the process found them, and the token and log files' permissions. */\nasync function auditEnvironment(context: CommandContext): Promise<Finding[]> {\n\tconst { settings } = context.loaded;\n\tconst findings: Finding[] = [];\n\tconst cacheProblem = await context.cache?.unwritable();\n\tif (cacheProblem !== undefined) {\n\t\tfindings.push(\n\t\t\twarning(\n\t\t\t\t`cache: ${settings.cache.dir} is not writable (${cacheProblem}); names are read from Asana each run (cache.enabled: false makes that intended)`,\n\t\t\t),\n\t\t);\n\t}\n\t// Opening the log stream fails later than it returns, so the file is probed here too.\n\tconst { file } = context.log;\n\tconst logProblem =\n\t\tcontext.log.problem ?? (typeof file === \"string\" ? await unwritableFile(file) : undefined);\n\tif (logProblem !== undefined) {\n\t\tfindings.push(\n\t\t\twarning(`log: ${file ?? \"\"} cannot be opened (${logProblem}); warnings reach stderr only`),\n\t\t);\n\t}\n\t// Created owner-only, but one that was there already keeps its mode.\n\tconst logInfo = typeof file === \"string\" ? await statIfPresent(file) : undefined;\n\tconst logExposure = typeof file === \"string\" ? exposureOf(file, logInfo?.mode) : undefined;\n\tif (logExposure !== undefined) {\n\t\tfindings.push(warning(`log: ${logExposure}`));\n\t}\n\tconst token = tokenFileWarning(context.token);\n\tif (token !== undefined) {\n\t\tfindings.push(warning(`token: ${token}`));\n\t}\n\treturn findings;\n}\n\nexport { auditEnvironment, auditReferences, policyWarnings, warning };\nexport type { Finding };\n","// Copyright 2026 Shinsuke Mori\n// SPDX-License-Identifier: Apache-2.0\n\nimport { cp, rm } from \"node:fs/promises\";\nimport { basename, join } from \"node:path\";\n\nimport { isObject, type JsonObject, parseJsonc } from \"../json.ts\";\nimport { messageOf } from \"../log.ts\";\nimport { POLICY_FILE, PROJECT_DIR, TOKEN_FILE } from \"../settings/paths.ts\";\nimport { firstWhere, isFile, patchedJson, readIfPresent } from \"../system.ts\";\nimport { parseYaml } from \"../yaml.ts\";\nimport { type Finding, warning } from \"./audit.ts\";\nimport { UsageError } from \"./context.ts\";\n\n/**\n * How a repository is wired for a coding agent: the gate as a project MCP\n * server in the agent's own config file, a copy of the skill where the agent\n * reads skills, and, where the agent honors one, a rule that keeps the token\n * file from it. The MCP server keeps every copy of the skill current.\n */\n\nconst SKILL = \"asana-gate\";\nconst TOKEN_DENY = `Read(./${PROJECT_DIR}/${TOKEN_FILE})`;\n\n/** What one agent reads. */\ninterface Agent {\n\treadonly name: string;\n\t/** The file its MCP servers are declared in, and the member they sit under. */\n\treadonly mcpFile: string;\n\treadonly serversKey: string;\n\t/** The directories it reads project skills from; `init` writes the first. */\n\treadonly skillsDirs: readonly [string, ...string[]];\n\t/** The file its standing instructions live in. */\n\treadonly instructionsFile: string;\n\t/** The settings file that takes a rule keeping it from the token file, when it honors one. */\n\treadonly tokenGuard?: string;\n}\n\nconst AGENTS: readonly Agent[] = [\n\t{\n\t\tname: \"claude-code\",\n\t\tmcpFile: \".mcp.json\",\n\t\tserversKey: \"mcpServers\",\n\t\tskillsDirs: [join(\".claude\", \"skills\")],\n\t\tinstructionsFile: \"CLAUDE.md\",\n\t\ttokenGuard: join(\".claude\", \"settings.json\"),\n\t},\n\t{\n\t\tname: \"vscode\",\n\t\tmcpFile: join(\".vscode\", \"mcp.json\"),\n\t\tserversKey: \"servers\",\n\t\tskillsDirs: [join(\".agents\", \"skills\"), join(\".github\", \"skills\"), join(\".claude\", \"skills\")],\n\t\tinstructionsFile: join(\".github\", \"copilot-instructions.md\"),\n\t},\n\t{\n\t\tname: \"cursor\",\n\t\tmcpFile: join(\".cursor\", \"mcp.json\"),\n\t\tserversKey: \"mcpServers\",\n\t\tskillsDirs: [join(\".agents\", \"skills\"), join(\".cursor\", \"skills\"), join(\".claude\", \"skills\")],\n\t\tinstructionsFile: \"AGENTS.md\",\n\t},\n];\n\n/** The agents `init --agent` knows. */\nconst AGENT_NAMES = AGENTS.map((agent) => agent.name);\n\n/** Every directory an agent may read the skill from, so that a copy anywhere is kept current. */\nconst SKILL_DIRS = [...new Set(AGENTS.flatMap((agent) => agent.skillsDirs))];\n\nconst usage = (message: string): Error => new UsageError(message);\n\n/** The agents the names stand for; an unknown name is a usage error. */\nfunction agentsNamed(names: readonly string[]): Agent[] {\n\treturn names.map((name) => {\n\t\tconst agent = AGENTS.find((candidate) => candidate.name === name);\n\t\tif (agent === undefined) {\n\t\t\tthrow usage(`unknown agent \"${name}\" (known: ${AGENT_NAMES.join(\", \")})`);\n\t\t}\n\t\treturn agent;\n\t});\n}\n\n/** The skill shipped in the package: `skills/asana-gate` beside `dist` (or beside `src` in a checkout). */\nasync function packagedSkillDir(): Promise<string> {\n\tconst here = import.meta.dirname;\n\tconst roots = [here, join(here, \"..\"), join(here, \"..\", \"..\")];\n\tconst root = await firstWhere(roots, (dir) => isFile(join(dir, \"skills\", SKILL, \"SKILL.md\")));\n\tif (root === undefined) {\n\t\tthrow new Error(\"the packaged skill is missing\");\n\t}\n\treturn join(root, \"skills\", SKILL);\n}\n\n/** A copy of the skill in the project: its directory, and the version its frontmatter carries. */\ninterface SkillCopy {\n\treadonly dir: string;\n\treadonly version: string;\n}\n\n/** The version in a copied SKILL.md's frontmatter, or `undefined` when no readable copy is at `dir`. */\nasync function copiedVersion(dir: string): Promise<string | undefined> {\n\tconst text = await readIfPresent(join(dir, \"SKILL.md\"));\n\tconst frontmatter =\n\t\ttext === undefined ? undefined : /^---\\r?\\n(?<yaml>.*?)\\r?\\n---/su.exec(text)?.groups?.yaml;\n\tif (frontmatter === undefined) {\n\t\treturn undefined;\n\t}\n\ttry {\n\t\tconst parsed = parseYaml(frontmatter, \"SKILL.md\", (message) => new Error(message));\n\t\tconst metadata = isObject(parsed) && isObject(parsed.metadata) ? parsed.metadata : {};\n\t\treturn typeof metadata.version === \"string\" ? metadata.version : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/** The copies of the skill in the project, wherever an agent reads them. */\nasync function skillCopies(projectDir: string): Promise<SkillCopy[]> {\n\tconst copies = await Promise.all(\n\t\tSKILL_DIRS.map(async (dir) => ({\n\t\t\tdir: join(dir, SKILL),\n\t\t\tversion: await copiedVersion(join(projectDir, dir, SKILL)),\n\t\t})),\n\t);\n\treturn copies.filter((copy): copy is SkillCopy => copy.version !== undefined);\n}\n\n/** Replaces `target` with a fresh copy of the packaged skill at `source`, its eval cases left out. */\nasync function copySkill(source: string, target: string): Promise<void> {\n\tawait rm(target, { recursive: true, force: true });\n\tawait cp(source, target, { recursive: true, filter: (path) => basename(path) !== \"evals\" });\n}\n\n/** The MCP server entry that starts the gate for this project, pinned to this version. */\nfunction serverEntry(version: string): JsonObject {\n\treturn { type: \"stdio\", command: \"npx\", args: [\"-y\", `${SKILL}@${version}`, \"mcp\"] };\n}\n\n/** The version the gate's entry in an agent's MCP file pins, when the entry is there. */\nfunction pinnedVersion(document: JsonObject, agent: Agent): string | undefined {\n\tconst servers = document[agent.serversKey];\n\tconst entry = isObject(servers) && isObject(servers[SKILL]) ? servers[SKILL] : {};\n\tconst args = Array.isArray(entry.args) ? (entry.args as unknown[]) : [];\n\tconst spec = args.find(\n\t\t(arg): arg is string => typeof arg === \"string\" && arg.startsWith(`${SKILL}@`),\n\t);\n\treturn spec?.slice(SKILL.length + 1);\n}\n\n/** What `init --agent` did, and what the person still has to do. */\ninterface Wiring {\n\treadonly written: string[];\n\t/** Per agent, the standing instructions to add and the file they belong in. */\n\treadonly instructions: { readonly file: string; readonly text: string }[];\n\treadonly notes: string[];\n}\n\n/** What an agent's standing instructions should say so that it reaches Asana only through the gate. */\nfunction instructionsFor(agent: Agent): string {\n\treturn [\n\t\t\"## Asana\",\n\t\t\"\",\n\t\t`Tasks for this repository live in the Asana project \"<project>\", reached only through asana-gate: the \\`asana-gate\\` MCP server in ${agent.mcpFile}, governed by ${PROJECT_DIR}/${POLICY_FILE}.`,\n\t\t`Read ${join(agent.skillsDirs[0], SKILL, \"SKILL.md\")} before touching Asana.`,\n\t\t`Never call the Asana API any other way, and never read ${PROJECT_DIR}/${TOKEN_FILE}.`,\n\t].join(\"\\n\");\n}\n\n/** Wires `projectDir` for `agents`: skill copies, MCP entries and, where honored, the token rule. */\nasync function wireAgents(\n\tprojectDir: string,\n\tagents: readonly Agent[],\n\tversion: string,\n): Promise<Wiring> {\n\tconst source = await packagedSkillDir();\n\tconst skillDirs = [...new Set(agents.map((agent) => agent.skillsDirs[0]))];\n\tconst guards = [\n\t\t...new Set(agents.map((agent) => agent.tokenGuard).filter((file) => file !== undefined)),\n\t];\n\t// Every file is read and patched first, so one that cannot be parsed leaves the project as it was.\n\tconst writes = await Promise.all([\n\t\t...agents.map((agent) =>\n\t\t\tpatchedJson(join(projectDir, agent.mcpFile), usage, (document) => {\n\t\t\t\tconst current = document[agent.serversKey];\n\t\t\t\tconst servers = isObject(current) ? current : {};\n\t\t\t\tservers[SKILL] = serverEntry(version);\n\t\t\t\tdocument[agent.serversKey] = servers;\n\t\t\t}),\n\t\t),\n\t\t...guards.map((file) =>\n\t\t\tpatchedJson(join(projectDir, file), usage, (document) => {\n\t\t\t\tconst permissions = isObject(document.permissions) ? document.permissions : {};\n\t\t\t\tconst deny = Array.isArray(permissions.deny) ? (permissions.deny as unknown[]) : [];\n\t\t\t\tif (!deny.includes(TOKEN_DENY)) {\n\t\t\t\t\tdeny.push(TOKEN_DENY);\n\t\t\t\t}\n\t\t\t\tpermissions.deny = deny;\n\t\t\t\tdocument.permissions = permissions;\n\t\t\t}),\n\t\t),\n\t]);\n\tawait Promise.all([\n\t\t...skillDirs.map((dir) => copySkill(source, join(projectDir, dir, SKILL))),\n\t\t...writes.map((write) => write()),\n\t]);\n\tconst unguarded = agents\n\t\t.filter((agent) => agent.tokenGuard === undefined)\n\t\t.map((agent) => agent.name);\n\treturn {\n\t\twritten: [\n\t\t\t...skillDirs.map((dir) => join(dir, SKILL)),\n\t\t\t...agents.map((agent) => agent.mcpFile),\n\t\t\t...guards,\n\t\t],\n\t\tinstructions: agents.map((agent) => ({\n\t\t\tfile: agent.instructionsFile,\n\t\t\ttext: instructionsFor(agent),\n\t\t})),\n\t\tnotes:\n\t\t\tunguarded.length === 0\n\t\t\t\t? []\n\t\t\t\t: [\n\t\t\t\t\t\t`${unguarded.join(\" and \")} cannot be kept from reading files in the project, so keep the token out of it: \"asana-gate token set --user\" or $ASANA_ACCESS_TOKEN.`,\n\t\t\t\t\t],\n\t};\n}\n\n/** Rewrites every copy of the skill in the project that is from another version; resolves to the directories refreshed. */\nasync function refreshSkillCopies(projectDir: string, version: string): Promise<string[]> {\n\tconst copies = await skillCopies(projectDir);\n\tconst stale = copies.filter((copy) => copy.version !== version);\n\tif (stale.length === 0) {\n\t\treturn [];\n\t}\n\tconst source = await packagedSkillDir();\n\tawait Promise.all(stale.map((copy) => copySkill(source, join(projectDir, copy.dir))));\n\treturn stale.map((copy) => copy.dir);\n}\n\n/** One agent's MCP file as `check` sees it: the version it pins, or why it cannot be read. */\ninterface Pin {\n\treadonly file: string;\n\treadonly version?: string;\n\treadonly problem?: string;\n}\n\nasync function pinOf(projectDir: string, agent: Agent): Promise<Pin> {\n\ttry {\n\t\tconst text = await readIfPresent(join(projectDir, agent.mcpFile));\n\t\tconst document = text === undefined ? undefined : parseJsonc(text, agent.mcpFile, usage);\n\t\tconst version = isObject(document) ? pinnedVersion(document, agent) : undefined;\n\t\treturn { file: agent.mcpFile, ...(version !== undefined && { version }) };\n\t} catch (error) {\n\t\treturn { file: agent.mcpFile, problem: messageOf(error) };\n\t}\n}\n\n/** Agent files that belong to another version of asana-gate than this one. */\nasync function auditAgentFiles(projectDir: string, version: string): Promise<Finding[]> {\n\tconst [copies, pins] = await Promise.all([\n\t\tskillCopies(projectDir),\n\t\tPromise.all(AGENTS.map((agent) => pinOf(projectDir, agent))),\n\t]);\n\treturn [\n\t\t...pins\n\t\t\t.filter((pin) => pin.problem !== undefined)\n\t\t\t.map((pin) => warning(`${pin.problem ?? \"\"}; the agent may not start the gate`)),\n\t\t...copies\n\t\t\t.filter((copy) => copy.version !== version)\n\t\t\t.map((copy) =>\n\t\t\t\twarning(\n\t\t\t\t\t`${copy.dir} is the skill of asana-gate ${copy.version}; this is ${version}: the MCP server refreshes it when it starts, or run \"asana-gate init --agent …\"`,\n\t\t\t\t),\n\t\t\t),\n\t\t...pins\n\t\t\t.filter((pin) => pin.version !== undefined && pin.version !== version)\n\t\t\t.map((pin) =>\n\t\t\t\twarning(\n\t\t\t\t\t`${pin.file} starts asana-gate ${pin.version ?? \"?\"}; this is ${version}: run \"asana-gate init --agent …\" to update it`,\n\t\t\t\t),\n\t\t\t),\n\t];\n}\n\nexport { AGENT_NAMES, agentsNamed, auditAgentFiles, refreshSkillCopies, wireAgents };\nexport type { Agent };\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"api-Cd3qXjya.mjs","names":[],"sources":["../src/cli/api.ts"],"sourcesContent":["// Copyright 2026 Shinsuke Mori\n// SPDX-License-Identifier: Apache-2.0\n\nimport { parseArgs } from \"node:util\";\n\nimport { isHttpMethod } from \"../gate/router.ts\";\nimport { GATED_OPTIONS, UsageError, usageRows } from \"./context.ts\";\nimport { readData } from \"./flags.ts\";\nimport { runGated } from \"./run.ts\";\n\nconst API_OPTIONS = {\n\tquery: {\n\t\ttype: \"string\",\n\t\tshort: \"q\",\n\t\tmultiple: true,\n\t\tplaceholder: \"<key=value>\",\n\t\tdescription: \"Query parameter (repeatable; opt_fields takes a comma list)\",\n\t},\n\tdata: {\n\t\ttype: \"string\",\n\t\tshort: \"d\",\n\t\tplaceholder: \"<json>\",\n\t\tdescription: 'Request body as JSON (\"@file\" reads a file, \"-\" reads stdin)',\n\t},\n\t...GATED_OPTIONS,\n} as const;\n\nconst USAGE = `Usage: asana-gate api <METHOD> <path> [options]\n\nCall any Asana REST operation through the policy. The path is the part below\n/api/1.0, for example /tasks/123 or /workspaces/456/tasks/search.\n\nThe response body is always printed as JSON.\n\nOptions:\n${usageRows(API_OPTIONS)}\n\nExamples:\n asana-gate api GET /tasks/123 -q opt_fields=name,completed\n asana-gate api POST /tasks -d '{\"name\": \"Write docs\", \"projects\": [\"123\"]}'\n asana-gate api PUT /tasks/123 -d @task.json`;\n\n/** Runs `asana-gate api <METHOD> <path>`. */\nasync function runApi(argv: readonly string[]): Promise<number> {\n\tconst { values, positionals } = parseArgs({\n\t\targs: [...argv],\n\t\toptions: API_OPTIONS,\n\t\tallowPositionals: true,\n\t\tstrict: true,\n\t});\n\tif (values.help === true) {\n\t\tconsole.log(USAGE);\n\t\treturn 0;\n\t}\n\tconst [methodArg, path] = positionals;\n\tconst method = methodArg?.toUpperCase();\n\tif (method === undefined || path === undefined || !isHttpMethod(method)) {\n\t\tthrow new UsageError(`api needs a method (GET, POST, PUT, DELETE) and a path\\n\\n${USAGE}`);\n\t}\n\tconst query: Record<string, string> = {};\n\tfor (const pair of values.query ?? []) {\n\t\tconst separator = pair.indexOf(\"=\");\n\t\tif (separator === -1) {\n\t\t\tthrow new UsageError(`--query expects key=value, got \"${pair}\"`);\n\t\t}\n\t\tquery[pair.slice(0, separator)] = pair.slice(separator + 1);\n\t}\n\tconst body =\n\t\tvalues.data === undefined ? undefined : await readData(values.data, values.directory);\n\treturn runGated(() => ({ method, path, query, body }), { ...values, json: true });\n}\n\nexport { runApi };\n"],"mappings":";;;;;;AAUA,MAAM,cAAc;CACnB,OAAO;EACN,MAAM;EACN,OAAO;EACP,UAAU;EACV,aAAa;EACb,aAAa;CACd;CACA,MAAM;EACL,MAAM;EACN,OAAO;EACP,aAAa;EACb,aAAa;CACd;CACA,GAAG;AACJ;AAEA,MAAM,QAAQ;;;;;;;;EAQZ,UAAU,WAAW,EAAE;;;;;;;AAQzB,eAAe,OAAO,MAA0C;CAC/D,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACzC,MAAM,CAAC,GAAG,IAAI;EACd,SAAS;EACT,kBAAkB;EAClB,QAAQ;CACT,CAAC;CACD,IAAI,OAAO,SAAS,MAAM;EACzB,QAAQ,IAAI,KAAK;EACjB,OAAO;CACR;CACA,MAAM,CAAC,WAAW,QAAQ;CAC1B,MAAM,SAAS,WAAW,YAAY;CACtC,IAAI,WAAW,KAAA,KAAa,SAAS,KAAA,KAAa,CAAC,aAAa,MAAM,GACrE,MAAM,IAAI,WAAW,6DAA6D,OAAO;CAE1F,MAAM,QAAgC,CAAC;CACvC,KAAK,MAAM,QAAQ,OAAO,SAAS,CAAC,GAAG;EACtC,MAAM,YAAY,KAAK,QAAQ,GAAG;EAClC,IAAI,cAAc,IACjB,MAAM,IAAI,WAAW,mCAAmC,KAAK,EAAE;EAEhE,MAAM,KAAK,MAAM,GAAG,SAAS,KAAK,KAAK,MAAM,YAAY,CAAC;CAC3D;CACA,MAAM,OACL,OAAO,SAAS,KAAA,IAAY,KAAA,IAAY,MAAM,SAAS,OAAO,MAAM,OAAO,SAAS;CACrF,OAAO,gBAAgB;EAAE;EAAQ;EAAM;EAAO;CAAK,IAAI;EAAE,GAAG;EAAQ,MAAM;CAAK,CAAC;AACjF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"check-bGxfSyj4.mjs","names":[],"sources":["../src/cli/check.ts"],"sourcesContent":["// Copyright 2026 Shinsuke Mori\n// SPDX-License-Identifier: Apache-2.0\n\nimport { parseArgs } from \"node:util\";\n\nimport { FactsLoader } from \"../gate/facts.ts\";\nimport { cacheEntries } from \"../gate/listing-cache.ts\";\nimport { type CompiledConstraints, type CompiledRule, PolicyError } from \"../policy/types.ts\";\nimport { auditAgentFiles } from \"./agent.ts\";\nimport { auditEnvironment, auditReferences, policyWarnings } from \"./audit.ts\";\nimport { COMMON_OPTIONS, usageRows } from \"./context.ts\";\nimport { describeUser } from \"./identity.ts\";\nimport { loadPolicy } from \"./policy.ts\";\nimport { createContext } from \"./session.ts\";\n\nconst USAGE = `Usage: asana-gate check [options]\n\nValidate the settings and the policy: the token works, every name resolves,\nevery gid the rules name still exists in the workspace, and the cache and log\ndirectories can be written. Problems make the command fail (exit code 1);\nwarnings do not.\n\nOptions:\n${usageRows(COMMON_OPTIONS)}`;\n\n/** `resource.member` for every member a per-resource map or set names, with custom fields by name. */\nfunction membersOf(\n\tlabels: ReadonlyMap<string, string>,\n\tbyResource: ReadonlyMap<string, ReadonlyMap<string, unknown> | ReadonlySet<string>>,\n): string[] {\n\treturn [...byResource].flatMap(([resource, members]) =>\n\t\t[...(members instanceof Set ? members : members.keys())].map((key: string) => {\n\t\t\tconst label = labels.get(key);\n\t\t\treturn label === undefined ? `${resource}.${key}` : `${resource} ${label}`;\n\t\t}),\n\t);\n}\n\nfunction describeConstraints(constraints: CompiledConstraints): string {\n\tconst clauses: [string, string[]][] = [\n\t\t[\"require\", membersOf(constraints.labels, constraints.require)],\n\t\t[\"apply\", membersOf(constraints.labels, constraints.apply)],\n\t\t[\"forbid\", membersOf(constraints.labels, constraints.forbid)],\n\t\t[\"redact\", membersOf(constraints.labels, constraints.redact)],\n\t\t[\"limit\", [...constraints.limit].map(([action, l]) => `${action} ${l.max} per ${l.per}`)],\n\t\t[\"confirm\", [...constraints.confirm]],\n\t];\n\treturn clauses\n\t\t.filter(([, items]) => items.length > 0)\n\t\t.map(([name, items]) => `${name} ${items.join(\", \")}`)\n\t\t.join(\"; \");\n}\n\nfunction describeActions(rule: CompiledRule): string {\n\tconst actions = [...rule.actions];\n\treturn actions.length > 6\n\t\t? `${actions.slice(0, 6).join(\", \")}, … (${actions.length} actions)`\n\t\t: actions.join(\", \");\n}\n\nfunction describeRule(rule: CompiledRule): string {\n\tconst where = rule.raw.where === undefined ? \"workspace\" : JSON.stringify(rule.raw.where);\n\tconst shown =\n\t\trule.constraints === undefined ? describeActions(rule) : describeConstraints(rule.constraints);\n\treturn ` rules[${rule.index}] ${rule.effect.padEnd(5)} level ${rule.specificity.level}.${rule.specificity.cross} where ${where}\\n ${shown}`;\n}\n\n/** A policy that names something Asana does not have is a problem `check` reports (exit 1), not a usage error. */\nfunction unresolved(error: unknown): undefined {\n\tif (!(error instanceof PolicyError)) {\n\t\tthrow error;\n\t}\n\tconsole.log(`problem: ${error.message}`);\n\tconsole.log(\"1 problems, 0 warnings\");\n\treturn undefined;\n}\n\nasync function runCheck(argv: readonly string[], version: string): Promise<number> {\n\tconst { values } = parseArgs({ args: [...argv], options: COMMON_OPTIONS, strict: true });\n\tif (values.help === true) {\n\t\tconsole.log(USAGE);\n\t\treturn 0;\n\t}\n\tconst context = await createContext(values);\n\tconst policy = await loadPolicy(context).catch(unresolved);\n\tif (policy === undefined) {\n\t\treturn 1;\n\t}\n\tconst { settings, projectDir } = context.loaded;\n\tconst loader = new FactsLoader({ client: context.client, policy, logger: context.logger });\n\tconst [references, environment, agent, listings] = await Promise.all([\n\t\tauditReferences(policy, loader),\n\t\tauditEnvironment(context),\n\t\tprojectDir === undefined ? [] : auditAgentFiles(projectDir, version),\n\t\tsettings.cache.enabled ? cacheEntries(settings.cache.dir) : 0,\n\t]);\n\tconst cache = settings.cache.enabled ? `${settings.cache.dir} (${listings} listings)` : \"off\";\n\tconsole.log(`policy: ${settings.policy ?? \"?\"}`);\n\tconsole.log(`workspace: ${policy.workspaceName} (${policy.workspace})`);\n\tconsole.log(`token: ${describeUser(policy.me)} from ${context.token.source}`);\n\tconsole.log(`cache: ${cache}`);\n\tconsole.log(`log: ${context.log.file ?? \"stderr only\"}`);\n\tconsole.log(`rules: ${policy.rules.length} compiled statements`);\n\tfor (const rule of policy.rules) {\n\t\tconsole.log(describeRule(rule));\n\t}\n\tconsole.log(`references: ${references.checked} objects the rules name, checked against Asana`);\n\tconst findings = [...policyWarnings(policy), ...references.findings, ...environment, ...agent];\n\tfor (const finding of findings) {\n\t\tconsole.log(`${finding.level}: ${finding.text}`);\n\t}\n\tconst problems = findings.filter((finding) => finding.level === \"problem\").length;\n\tconst warnings = findings.length - problems;\n\tconsole.log(findings.length === 0 ? \"ok\" : `${problems} problems, ${warnings} warnings`);\n\treturn problems === 0 ? 0 : 1;\n}\n\nexport { runCheck };\n"],"mappings":"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"}
|