@ball-lang/cli 0.1.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/LICENSE +21 -0
- package/README.md +81 -0
- package/dist/capability_analyzer.d.ts +123 -0
- package/dist/capability_analyzer.d.ts.map +1 -0
- package/dist/capability_analyzer.js +311 -0
- package/dist/capability_analyzer.js.map +1 -0
- package/dist/capability_table.d.ts +24 -0
- package/dist/capability_table.d.ts.map +1 -0
- package/dist/capability_table.js +337 -0
- package/dist/capability_table.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +216 -0
- package/dist/index.js.map +1 -0
- package/package.json +66 -0
- package/src/capability_analyzer.ts +467 -0
- package/src/capability_table.ts +382 -0
- package/src/index.ts +245 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ball Language Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
[](https://www.npmjs.com/package/@ball-lang/cli)
|
|
2
|
+
|
|
3
|
+
# @ball-lang/cli
|
|
4
|
+
|
|
5
|
+
Command-line interface for the [Ball programming language](https://github.com/ball-lang/ball). Runs Ball programs and performs static capability analysis, powered by [`@ball-lang/engine`](https://www.npmjs.com/package/@ball-lang/engine).
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g @ball-lang/cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or run it without installing:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx @ball-lang/cli run my_program.ball.json
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Commands
|
|
20
|
+
|
|
21
|
+
### `ball run <program.ball.json>`
|
|
22
|
+
|
|
23
|
+
Execute a Ball program. Writes `std.print` output to stdout.
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
ball run examples/hello_world/hello_world.ball.json
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### `ball audit <program.ball.json>`
|
|
30
|
+
|
|
31
|
+
Static capability analysis. Walks the expression tree of every user-defined function and reports which side-effect categories are used. Because every side effect in Ball flows through a named base function, this analysis is provably complete -- not heuristic.
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
ball audit my_program.ball.json
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Example output:
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
Ball Capability Audit: path v1.9.1
|
|
41
|
+
============================================================
|
|
42
|
+
|
|
43
|
+
Capabilities:
|
|
44
|
+
✓ pure (pure computation)
|
|
45
|
+
⚠ io (2 call sites: main.main → std.print, main.main → std.print)
|
|
46
|
+
✗ NONE: filesystem, network, process, memory, concurrency, random
|
|
47
|
+
|
|
48
|
+
Summary: LOW RISK
|
|
49
|
+
1 functions: 0 pure, 1 effectful
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
#### Audit flags
|
|
53
|
+
|
|
54
|
+
| Flag | Description |
|
|
55
|
+
|------|-------------|
|
|
56
|
+
| `--output <path>` | Write the structured JSON report to `<path>`. |
|
|
57
|
+
| `--deny <caps>` | Comma-separated capabilities to deny. Exits with code 1 on any violation (e.g. `--deny fs,network`). |
|
|
58
|
+
| `--reachable-only` | Only analyze functions transitively reachable from the entry function. |
|
|
59
|
+
| `--json` | Emit the JSON report to stdout instead of the text report. |
|
|
60
|
+
|
|
61
|
+
Capability categories: `pure`, `io`, `fs`, `process`, `time`, `random`, `memory`, `concurrency`, `network`, `async`.
|
|
62
|
+
|
|
63
|
+
### `ball --version`
|
|
64
|
+
|
|
65
|
+
Prints the CLI version.
|
|
66
|
+
|
|
67
|
+
### `ball --help`
|
|
68
|
+
|
|
69
|
+
Prints usage information.
|
|
70
|
+
|
|
71
|
+
## Policy enforcement in CI
|
|
72
|
+
|
|
73
|
+
Fail a CI job if a Ball program gains filesystem or network access:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
ball audit my_program.ball.json --deny fs,network
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## License
|
|
80
|
+
|
|
81
|
+
MIT
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static capability analysis for Ball programs.
|
|
3
|
+
*
|
|
4
|
+
* Walks the expression tree of every function in a Program and reports
|
|
5
|
+
* which base functions are called, categorized by side-effect capability.
|
|
6
|
+
* Since every side effect in Ball flows through a named base function,
|
|
7
|
+
* this analysis is provably complete — not heuristic.
|
|
8
|
+
*
|
|
9
|
+
* Ported from `dart/shared/lib/capability_analyzer.dart`.
|
|
10
|
+
*/
|
|
11
|
+
import type { Capability } from './capability_table.ts';
|
|
12
|
+
export interface Program {
|
|
13
|
+
name?: string;
|
|
14
|
+
version?: string;
|
|
15
|
+
modules: Module[];
|
|
16
|
+
entryModule: string;
|
|
17
|
+
entryFunction: string;
|
|
18
|
+
}
|
|
19
|
+
export interface Module {
|
|
20
|
+
name: string;
|
|
21
|
+
functions: FunctionDef[];
|
|
22
|
+
}
|
|
23
|
+
export interface FunctionDef {
|
|
24
|
+
name: string;
|
|
25
|
+
isBase?: boolean;
|
|
26
|
+
body?: Expression;
|
|
27
|
+
}
|
|
28
|
+
export interface Expression {
|
|
29
|
+
call?: FunctionCall;
|
|
30
|
+
literal?: Literal;
|
|
31
|
+
reference?: {
|
|
32
|
+
name: string;
|
|
33
|
+
};
|
|
34
|
+
fieldAccess?: {
|
|
35
|
+
object?: Expression;
|
|
36
|
+
field: string;
|
|
37
|
+
};
|
|
38
|
+
messageCreation?: {
|
|
39
|
+
fields: FieldValuePair[];
|
|
40
|
+
};
|
|
41
|
+
block?: Block;
|
|
42
|
+
lambda?: Lambda;
|
|
43
|
+
}
|
|
44
|
+
export interface FunctionCall {
|
|
45
|
+
module?: string;
|
|
46
|
+
function: string;
|
|
47
|
+
input?: Expression;
|
|
48
|
+
}
|
|
49
|
+
export interface Literal {
|
|
50
|
+
listValue?: {
|
|
51
|
+
elements: Expression[];
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export interface FieldValuePair {
|
|
55
|
+
name: string;
|
|
56
|
+
value: Expression;
|
|
57
|
+
}
|
|
58
|
+
export interface Block {
|
|
59
|
+
statements: Statement[];
|
|
60
|
+
result?: Expression;
|
|
61
|
+
}
|
|
62
|
+
export interface Statement {
|
|
63
|
+
let?: {
|
|
64
|
+
name: string;
|
|
65
|
+
value: Expression;
|
|
66
|
+
};
|
|
67
|
+
expression?: Expression;
|
|
68
|
+
}
|
|
69
|
+
export interface Lambda {
|
|
70
|
+
body: Expression;
|
|
71
|
+
}
|
|
72
|
+
export interface CallSite {
|
|
73
|
+
module: string;
|
|
74
|
+
function: string;
|
|
75
|
+
calleeModule: string;
|
|
76
|
+
calleeFunction: string;
|
|
77
|
+
}
|
|
78
|
+
export interface FunctionCapability {
|
|
79
|
+
module: string;
|
|
80
|
+
function: string;
|
|
81
|
+
capabilities: Capability[];
|
|
82
|
+
}
|
|
83
|
+
export interface CapabilityEntry {
|
|
84
|
+
capability: Capability;
|
|
85
|
+
riskLevel: string;
|
|
86
|
+
callSites: CallSite[];
|
|
87
|
+
}
|
|
88
|
+
export interface CapabilitySummary {
|
|
89
|
+
isPure: boolean;
|
|
90
|
+
readsFilesystem: boolean;
|
|
91
|
+
writesFilesystem: boolean;
|
|
92
|
+
readsStdin: boolean;
|
|
93
|
+
writesStdout: boolean;
|
|
94
|
+
writesStderr: boolean;
|
|
95
|
+
readsEnvironment: boolean;
|
|
96
|
+
controlsProcess: boolean;
|
|
97
|
+
usesMemory: boolean;
|
|
98
|
+
usesTime: boolean;
|
|
99
|
+
usesRandom: boolean;
|
|
100
|
+
usesConcurrency: boolean;
|
|
101
|
+
usesNetwork: boolean;
|
|
102
|
+
totalFunctions: number;
|
|
103
|
+
pureFunctions: number;
|
|
104
|
+
effectfulFunctions: number;
|
|
105
|
+
}
|
|
106
|
+
export interface BallCapabilityReport {
|
|
107
|
+
programName: string;
|
|
108
|
+
programVersion: string;
|
|
109
|
+
capabilities: CapabilityEntry[];
|
|
110
|
+
functions: FunctionCapability[];
|
|
111
|
+
summary: CapabilitySummary;
|
|
112
|
+
}
|
|
113
|
+
export interface AnalyzeOptions {
|
|
114
|
+
/** If true, only analyze functions transitively reachable from the entry. */
|
|
115
|
+
reachableOnly?: boolean;
|
|
116
|
+
}
|
|
117
|
+
/** Analyze a Ball program and return a structured capability report. */
|
|
118
|
+
export declare function analyzeCapabilities(program: Program, options?: AnalyzeOptions): BallCapabilityReport;
|
|
119
|
+
/** Format a capability report as human-readable text. */
|
|
120
|
+
export declare function formatCapabilityReport(report: BallCapabilityReport): string;
|
|
121
|
+
/** Check a report against a deny list. Returns list of violations (empty = pass). */
|
|
122
|
+
export declare function checkPolicy(report: BallCapabilityReport, deny: ReadonlySet<string>): string[];
|
|
123
|
+
//# sourceMappingURL=capability_analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability_analyzer.d.ts","sourceRoot":"","sources":["../src/capability_analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static capability analysis for Ball programs.
|
|
3
|
+
*
|
|
4
|
+
* Walks the expression tree of every function in a Program and reports
|
|
5
|
+
* which base functions are called, categorized by side-effect capability.
|
|
6
|
+
* Since every side effect in Ball flows through a named base function,
|
|
7
|
+
* this analysis is provably complete — not heuristic.
|
|
8
|
+
*
|
|
9
|
+
* Ported from `dart/shared/lib/capability_analyzer.dart`.
|
|
10
|
+
*/
|
|
11
|
+
import { ALL_CAPABILITIES, capabilityRiskLevel, lookupCapability, } from "./capability_table.js";
|
|
12
|
+
/** Analyze a Ball program and return a structured capability report. */
|
|
13
|
+
export function analyzeCapabilities(program, options = {}) {
|
|
14
|
+
return new Analyzer(program, options.reachableOnly ?? false).analyze();
|
|
15
|
+
}
|
|
16
|
+
class Analyzer {
|
|
17
|
+
program;
|
|
18
|
+
reachableOnly;
|
|
19
|
+
fnCaps = new Map();
|
|
20
|
+
capCallSites = new Map();
|
|
21
|
+
baseModules = new Set();
|
|
22
|
+
constructor(program, reachableOnly) {
|
|
23
|
+
this.program = program;
|
|
24
|
+
this.reachableOnly = reachableOnly;
|
|
25
|
+
}
|
|
26
|
+
analyze() {
|
|
27
|
+
this.identifyBaseModules();
|
|
28
|
+
if (this.reachableOnly) {
|
|
29
|
+
this.analyzeReachable();
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
this.analyzeAll();
|
|
33
|
+
}
|
|
34
|
+
return this.buildReport();
|
|
35
|
+
}
|
|
36
|
+
identifyBaseModules() {
|
|
37
|
+
for (const mod of this.program.modules) {
|
|
38
|
+
if (mod.functions.length === 0)
|
|
39
|
+
continue;
|
|
40
|
+
const allBase = mod.functions.every((f) => f.isBase === true);
|
|
41
|
+
if (allBase)
|
|
42
|
+
this.baseModules.add(mod.name);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
analyzeAll() {
|
|
46
|
+
for (const mod of this.program.modules) {
|
|
47
|
+
if (this.baseModules.has(mod.name))
|
|
48
|
+
continue;
|
|
49
|
+
for (const fn of mod.functions) {
|
|
50
|
+
if (fn.isBase)
|
|
51
|
+
continue;
|
|
52
|
+
const caps = new Set();
|
|
53
|
+
if (fn.body)
|
|
54
|
+
this.walkExpression(fn.body, mod.name, fn.name, caps);
|
|
55
|
+
this.fnCaps.set(`${mod.name}.${fn.name}`, caps);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
analyzeReachable() {
|
|
60
|
+
const visited = new Set();
|
|
61
|
+
const entryKey = `${this.program.entryModule}.${this.program.entryFunction}`;
|
|
62
|
+
this.analyzeFunction(entryKey, visited);
|
|
63
|
+
}
|
|
64
|
+
analyzeFunction(key, visited) {
|
|
65
|
+
if (visited.has(key))
|
|
66
|
+
return;
|
|
67
|
+
visited.add(key);
|
|
68
|
+
const parts = key.split('.');
|
|
69
|
+
if (parts.length < 2)
|
|
70
|
+
return;
|
|
71
|
+
const moduleName = parts[0];
|
|
72
|
+
const fnName = parts.slice(1).join('.');
|
|
73
|
+
if (this.baseModules.has(moduleName))
|
|
74
|
+
return;
|
|
75
|
+
for (const mod of this.program.modules) {
|
|
76
|
+
if (mod.name !== moduleName)
|
|
77
|
+
continue;
|
|
78
|
+
for (const fn of mod.functions) {
|
|
79
|
+
if (fn.name !== fnName)
|
|
80
|
+
continue;
|
|
81
|
+
if (fn.isBase)
|
|
82
|
+
return;
|
|
83
|
+
const caps = new Set();
|
|
84
|
+
const callees = new Set();
|
|
85
|
+
if (fn.body) {
|
|
86
|
+
this.walkExpression(fn.body, moduleName, fnName, caps, callees);
|
|
87
|
+
}
|
|
88
|
+
this.fnCaps.set(key, caps);
|
|
89
|
+
for (const callee of callees) {
|
|
90
|
+
this.analyzeFunction(callee, visited);
|
|
91
|
+
const calleeCaps = this.fnCaps.get(callee);
|
|
92
|
+
if (calleeCaps)
|
|
93
|
+
for (const c of calleeCaps)
|
|
94
|
+
caps.add(c);
|
|
95
|
+
}
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
walkExpression(expr, ctxModule, ctxFunction, caps, callees) {
|
|
101
|
+
if (expr.call) {
|
|
102
|
+
this.walkCall(expr.call, ctxModule, ctxFunction, caps, callees);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (expr.literal) {
|
|
106
|
+
if (expr.literal.listValue) {
|
|
107
|
+
for (const elem of expr.literal.listValue.elements) {
|
|
108
|
+
this.walkExpression(elem, ctxModule, ctxFunction, caps, callees);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (expr.block) {
|
|
114
|
+
for (const stmt of expr.block.statements) {
|
|
115
|
+
if (stmt.let) {
|
|
116
|
+
this.walkExpression(stmt.let.value, ctxModule, ctxFunction, caps, callees);
|
|
117
|
+
}
|
|
118
|
+
if (stmt.expression) {
|
|
119
|
+
this.walkExpression(stmt.expression, ctxModule, ctxFunction, caps, callees);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (expr.block.result) {
|
|
123
|
+
this.walkExpression(expr.block.result, ctxModule, ctxFunction, caps, callees);
|
|
124
|
+
}
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (expr.lambda) {
|
|
128
|
+
this.walkExpression(expr.lambda.body, ctxModule, ctxFunction, caps, callees);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (expr.messageCreation) {
|
|
132
|
+
for (const field of expr.messageCreation.fields) {
|
|
133
|
+
this.walkExpression(field.value, ctxModule, ctxFunction, caps, callees);
|
|
134
|
+
}
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (expr.fieldAccess?.object) {
|
|
138
|
+
this.walkExpression(expr.fieldAccess.object, ctxModule, ctxFunction, caps, callees);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
// reference or unset: nothing to walk
|
|
142
|
+
}
|
|
143
|
+
walkCall(call, ctxModule, ctxFunction, caps, callees) {
|
|
144
|
+
const moduleName = call.module && call.module.length > 0 ? call.module : ctxModule;
|
|
145
|
+
const fnName = call.function;
|
|
146
|
+
const cap = lookupCapability(moduleName, fnName);
|
|
147
|
+
if (cap !== undefined) {
|
|
148
|
+
caps.add(cap);
|
|
149
|
+
if (cap !== 'pure') {
|
|
150
|
+
const list = this.capCallSites.get(cap) ?? [];
|
|
151
|
+
list.push({
|
|
152
|
+
module: ctxModule,
|
|
153
|
+
function: ctxFunction,
|
|
154
|
+
calleeModule: moduleName,
|
|
155
|
+
calleeFunction: fnName,
|
|
156
|
+
});
|
|
157
|
+
this.capCallSites.set(cap, list);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
callees?.add(`${moduleName}.${fnName}`);
|
|
162
|
+
}
|
|
163
|
+
if (call.input) {
|
|
164
|
+
this.walkExpression(call.input, ctxModule, ctxFunction, caps, callees);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
buildReport() {
|
|
168
|
+
const allCaps = new Set();
|
|
169
|
+
let totalFns = 0;
|
|
170
|
+
let pureFns = 0;
|
|
171
|
+
let effectfulFns = 0;
|
|
172
|
+
const functions = [];
|
|
173
|
+
for (const [key, caps] of this.fnCaps) {
|
|
174
|
+
const dot = key.indexOf('.');
|
|
175
|
+
const mod = key.substring(0, dot);
|
|
176
|
+
const fn = key.substring(dot + 1);
|
|
177
|
+
functions.push({
|
|
178
|
+
module: mod,
|
|
179
|
+
function: fn,
|
|
180
|
+
capabilities: Array.from(caps),
|
|
181
|
+
});
|
|
182
|
+
for (const c of caps)
|
|
183
|
+
allCaps.add(c);
|
|
184
|
+
totalFns++;
|
|
185
|
+
const onlyPure = Array.from(caps).every((c) => c === 'pure');
|
|
186
|
+
if (onlyPure)
|
|
187
|
+
pureFns++;
|
|
188
|
+
else
|
|
189
|
+
effectfulFns++;
|
|
190
|
+
}
|
|
191
|
+
const capabilities = [];
|
|
192
|
+
for (const cap of ALL_CAPABILITIES) {
|
|
193
|
+
if (!allCaps.has(cap) && cap !== 'pure')
|
|
194
|
+
continue;
|
|
195
|
+
const sites = this.capCallSites.get(cap) ?? [];
|
|
196
|
+
if (cap === 'pure' && sites.length === 0 && allCaps.has(cap)) {
|
|
197
|
+
capabilities.push({
|
|
198
|
+
capability: cap,
|
|
199
|
+
riskLevel: capabilityRiskLevel[cap],
|
|
200
|
+
callSites: [],
|
|
201
|
+
});
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
if (sites.length > 0) {
|
|
205
|
+
capabilities.push({
|
|
206
|
+
capability: cap,
|
|
207
|
+
riskLevel: capabilityRiskLevel[cap],
|
|
208
|
+
callSites: sites.slice(),
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
const ioSites = this.capCallSites.get('io') ?? [];
|
|
213
|
+
const summary = {
|
|
214
|
+
isPure: Array.from(allCaps).every((c) => c === 'pure'),
|
|
215
|
+
readsFilesystem: allCaps.has('fs'),
|
|
216
|
+
writesFilesystem: allCaps.has('fs'),
|
|
217
|
+
readsStdin: ioSites.some((s) => s.calleeFunction === 'read_line'),
|
|
218
|
+
writesStdout: ioSites.some((s) => s.calleeFunction === 'print' || s.calleeFunction === 'print_error'),
|
|
219
|
+
writesStderr: ioSites.some((s) => s.calleeFunction === 'print_error'),
|
|
220
|
+
readsEnvironment: ioSites.some((s) => s.calleeFunction === 'env_get' || s.calleeFunction === 'args_get'),
|
|
221
|
+
controlsProcess: allCaps.has('process'),
|
|
222
|
+
usesMemory: allCaps.has('memory'),
|
|
223
|
+
usesTime: allCaps.has('time'),
|
|
224
|
+
usesRandom: allCaps.has('random'),
|
|
225
|
+
usesConcurrency: allCaps.has('concurrency'),
|
|
226
|
+
usesNetwork: allCaps.has('network'),
|
|
227
|
+
totalFunctions: totalFns,
|
|
228
|
+
pureFunctions: pureFns,
|
|
229
|
+
effectfulFunctions: effectfulFns,
|
|
230
|
+
};
|
|
231
|
+
return {
|
|
232
|
+
programName: this.program.name ?? '',
|
|
233
|
+
programVersion: this.program.version ?? '',
|
|
234
|
+
capabilities,
|
|
235
|
+
functions,
|
|
236
|
+
summary,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
// ── Formatting & policy helpers ─────────────────────────────────────────────
|
|
241
|
+
/** Format a capability report as human-readable text. */
|
|
242
|
+
export function formatCapabilityReport(report) {
|
|
243
|
+
const lines = [];
|
|
244
|
+
const name = report.programName || '<unnamed>';
|
|
245
|
+
const version = report.programVersion || '0.0.0';
|
|
246
|
+
lines.push(`Ball Capability Audit: ${name} v${version}`);
|
|
247
|
+
lines.push('='.repeat(60));
|
|
248
|
+
lines.push('');
|
|
249
|
+
lines.push('Capabilities:');
|
|
250
|
+
for (const entry of report.capabilities) {
|
|
251
|
+
const icon = entry.riskLevel === 'none' ? '\u2713' : '\u26A0';
|
|
252
|
+
const siteCount = entry.callSites.length;
|
|
253
|
+
if (siteCount === 0) {
|
|
254
|
+
lines.push(` ${icon} ${entry.capability} (pure computation)`);
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
const sites = entry.callSites
|
|
258
|
+
.map((s) => `${s.module}.${s.function} \u2192 ${s.calleeModule}.${s.calleeFunction}`)
|
|
259
|
+
.join(', ');
|
|
260
|
+
lines.push(` ${icon} ${entry.capability} (${siteCount} call sites: ${sites})`);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
const absent = [];
|
|
264
|
+
const s = report.summary;
|
|
265
|
+
if (!s.readsFilesystem && !s.writesFilesystem)
|
|
266
|
+
absent.push('filesystem');
|
|
267
|
+
if (!s.usesNetwork)
|
|
268
|
+
absent.push('network');
|
|
269
|
+
if (!s.controlsProcess)
|
|
270
|
+
absent.push('process');
|
|
271
|
+
if (!s.usesMemory)
|
|
272
|
+
absent.push('memory');
|
|
273
|
+
if (!s.usesConcurrency)
|
|
274
|
+
absent.push('concurrency');
|
|
275
|
+
if (!s.usesRandom)
|
|
276
|
+
absent.push('random');
|
|
277
|
+
if (absent.length > 0) {
|
|
278
|
+
lines.push(` \u2717 NONE: ${absent.join(', ')}`);
|
|
279
|
+
}
|
|
280
|
+
lines.push('');
|
|
281
|
+
const risk = s.isPure
|
|
282
|
+
? 'NO RISK \u2014 pure computation only'
|
|
283
|
+
: s.controlsProcess || s.usesMemory || s.usesNetwork
|
|
284
|
+
? 'HIGH RISK'
|
|
285
|
+
: s.readsFilesystem || s.writesFilesystem || s.usesConcurrency
|
|
286
|
+
? 'MEDIUM RISK'
|
|
287
|
+
: 'LOW RISK';
|
|
288
|
+
lines.push(`Summary: ${risk}`);
|
|
289
|
+
lines.push(` ${s.totalFunctions} functions: ${s.pureFunctions} pure, ${s.effectfulFunctions} effectful`);
|
|
290
|
+
lines.push('');
|
|
291
|
+
lines.push('Per-function breakdown:');
|
|
292
|
+
for (const fn of report.functions) {
|
|
293
|
+
const caps = fn.capabilities.filter((c) => c !== 'pure');
|
|
294
|
+
const label = caps.length === 0 ? 'pure' : caps.join(', ');
|
|
295
|
+
lines.push(` ${fn.module}.${fn.function} \u2192 ${label}`);
|
|
296
|
+
}
|
|
297
|
+
return lines.join('\n') + '\n';
|
|
298
|
+
}
|
|
299
|
+
/** Check a report against a deny list. Returns list of violations (empty = pass). */
|
|
300
|
+
export function checkPolicy(report, deny) {
|
|
301
|
+
const violations = [];
|
|
302
|
+
for (const entry of report.capabilities) {
|
|
303
|
+
if (!deny.has(entry.capability))
|
|
304
|
+
continue;
|
|
305
|
+
for (const site of entry.callSites) {
|
|
306
|
+
violations.push(`${entry.capability}: ${site.module}.${site.function} calls ${site.calleeModule}.${site.calleeFunction}`);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return violations;
|
|
310
|
+
}
|
|
311
|
+
//# sourceMappingURL=capability_analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability_analyzer.js","sourceRoot":"","sources":["../src/capability_analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static mapping of every Ball base function to its capability category.
|
|
3
|
+
*
|
|
4
|
+
* Since every side effect in Ball flows through a named base function in a
|
|
5
|
+
* known module, this table is provably complete. No function can perform I/O,
|
|
6
|
+
* access the filesystem, or spawn threads without appearing here.
|
|
7
|
+
*
|
|
8
|
+
* Ported from `dart/shared/lib/capability_table.dart`.
|
|
9
|
+
*/
|
|
10
|
+
/** Capability categories for Ball base functions. */
|
|
11
|
+
export type Capability = 'pure' | 'io' | 'fs' | 'process' | 'time' | 'random' | 'memory' | 'concurrency' | 'network' | 'async';
|
|
12
|
+
/** Canonical ordering of capabilities (matches the Dart enum order). */
|
|
13
|
+
export declare const ALL_CAPABILITIES: readonly Capability[];
|
|
14
|
+
/** Risk level associated with each capability. */
|
|
15
|
+
export declare const capabilityRiskLevel: Record<Capability, string>;
|
|
16
|
+
/**
|
|
17
|
+
* Lookup the capability of a base function call.
|
|
18
|
+
*
|
|
19
|
+
* Returns `undefined` for non-base / user-defined functions (which are pure
|
|
20
|
+
* by construction — they can only call other functions in this table).
|
|
21
|
+
*/
|
|
22
|
+
export declare function lookupCapability(module: string, fn: string): Capability | undefined;
|
|
23
|
+
export declare const CAPABILITY_TABLE: Readonly<Record<string, Capability>>;
|
|
24
|
+
//# sourceMappingURL=capability_table.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability_table.d.ts","sourceRoot":"","sources":["../src/capability_table.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,qDAAqD;AACrD,MAAM,MAAM,UAAU,GAClB,MAAM,GACN,IAAI,GACJ,IAAI,GACJ,SAAS,GACT,MAAM,GACN,QAAQ,GACR,QAAQ,GACR,aAAa,GACb,SAAS,GACT,OAAO,CAAC;AAEZ,wEAAwE;AACxE,eAAO,MAAM,gBAAgB,EAAE,SAAS,UAAU,EAWjD,CAAC;AAEF,kDAAkD;AAClD,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAW1D,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,GACT,UAAU,GAAG,SAAS,CAExB;AAED,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CA6TjE,CAAC"}
|