staisix-cli 1.0.0 β 1.0.2
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/.github/workflows/publish.yml +29 -0
- package/README.md +89 -0
- package/index.js +65 -34
- package/package.json +7 -2
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: Publish Package to NPM Registry
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [created] # Fires automatically whenever you tag an official launch release in GitHub!
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
id-token: write # CRITICAL! This requests the secure OIDC cryptographic token required for Trusted Publishing!
|
|
13
|
+
steps:
|
|
14
|
+
- name: Checkout Codebase Repository
|
|
15
|
+
uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Initialize Node.js Environment Runtime
|
|
18
|
+
uses: actions/setup-node@v4
|
|
19
|
+
with:
|
|
20
|
+
node-version: '20'
|
|
21
|
+
registry-url: 'https://npmjs.org'
|
|
22
|
+
|
|
23
|
+
- name: Sync Project Dependencies
|
|
24
|
+
run: npm ci
|
|
25
|
+
|
|
26
|
+
- name: Execute Automated Global CDN Deployment
|
|
27
|
+
run: npm publish --provenance --access public
|
|
28
|
+
env:
|
|
29
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} # Bypassed dynamically via your secure Trusted Publisher handshake loop!
|
package/README.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# staisix-cli π‘
|
|
2
|
+
|
|
3
|
+
[](https://npmjs.com)
|
|
4
|
+
[](https://opensource.org)
|
|
5
|
+
|
|
6
|
+
> **Continuous Policy-as-Code AI Governance.** Shift compliance left by embedding automated regulatory guardrails directly inside your local developer GitOps pipelines.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## π Overview
|
|
11
|
+
|
|
12
|
+
**STAISIX** turns complex international AI regulations (including the **EU AI Act**, **NIST AI RMF**, and **ISO/IEC 42001**) into deterministic, automated filesystem inspection checks.
|
|
13
|
+
|
|
14
|
+
The `staisix-cli` binary intercepts non-compliant model repository builds directly within your local CI/CD engine runtimesβhalting code promotions before non-compliant systems reach live production networks, while delivering 15-minute diagnostic self-remediation logs directly in the developer terminal console.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## π οΈ Installation
|
|
19
|
+
|
|
20
|
+
Install the compliance scanning engine globally on your system path via the Node Package Manager:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install -g staisix-cli
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## π Quick Start: 3-Step Repository Initialization
|
|
29
|
+
|
|
30
|
+
### 1. Provision Your Local Configuration File
|
|
31
|
+
Create a new file named exactly `staisix.config.json` right inside your root repository folder path to define your tenant identification parameters:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"organization": "Your Company Name",
|
|
36
|
+
"aiSystemName": "your_repository_microservice_name"
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 2. Establish Your Evidence Asset Folder Tree
|
|
41
|
+
STAISIX evaluates your framework controls locally through decoupled evidence artifacts. Create your local subfolder structure:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
mkdir -p .staisix/evidence
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 3. Execute Your First Compliance Scan
|
|
48
|
+
To evaluate your repository filesystem against active global compliance guardrails, run the binary scanner natively:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
staisix scan
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## π Evaluated Framework Controls Mapping
|
|
57
|
+
|
|
58
|
+
| Control Token ID | Checked Repository File Asset | Cross-Regulatory Legal Alignments |
|
|
59
|
+
| :--- | :--- | :--- |
|
|
60
|
+
| **`STX-OVERSIGHT-01`** | `.staisix/evidence/oversight_policy.md` | β’ **EU AI Act:** Article 14 (Human Oversight)<br>β’ **NIST AI RMF:** GOVERN 1.2 (Roles & Responsibilities)<br>β’ **ISO 42001:** Annex A.7.4 (Human Supervision) |
|
|
61
|
+
| **`STX-DATA-02`** | `.staisix/evidence/data_manifest.csv` | β’ **EU AI Act:** Article 10 (Data Governance)<br>β’ **NIST AI RMF:** MEASURE 2.1 (Data Lineage Tracing)<br>β’ **ISO 42001:** Annex A.8.2 (Data for AI Systems) |
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## π Self-Remediation Workflow (How to Clear Blocker Gates)
|
|
66
|
+
|
|
67
|
+
If an automated scan intercepts your build layout and returns a hard exit code `1` (`π [BUILD ERROR]`), read your terminal output logs to identify the missing documentation.
|
|
68
|
+
|
|
69
|
+
To "self-heal" the pipeline and unblock your release timeline, populate your nested `.staisix/evidence/` folder path with the required framework compliance artifacts:
|
|
70
|
+
|
|
71
|
+
* **To clear `STX-OVERSIGHT-01`:** Document your human-in-the-loop oversight mechanisms inside `.staisix/evidence/oversight_policy.md`.
|
|
72
|
+
* **To clear `STX-DATA-02`:** Document your training dataset characteristics, data provenance parameters, and compliance hashes inside `.staisix/evidence/data_manifest.csv`.
|
|
73
|
+
|
|
74
|
+
Once the missing evidence files exist in the repository, re-running `staisix scan` will pass instantly, print a green success log, and authorize a successful production code promotion with exit code `0`.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## π Data Privacy & Multi-Tenant Security Blueprint
|
|
79
|
+
|
|
80
|
+
The `staisix-cli` utility respects strict corporate data privacy standards. **Our scanner never accesses, views, or ingests your proprietary model weights or source code files.**
|
|
81
|
+
|
|
82
|
+
The scanning engine performs all logical evaluation loops completely within your local system's isolated runtime runtime memory. Only a passing/blocked status flag, your system identification tokens, and the triggered failure Control IDs are transmitted over the web to our secure multi-tenant ledger.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## β‘ Support & Beta Pilot Access
|
|
87
|
+
To acquire a verified corporate registration key or gain access to your cloud GRC Executive Summary Monitoring dashboards, visit your portal at [staisix.com](https://staisix.com).
|
|
88
|
+
|
|
89
|
+
*For priority technical support channels, connect with your assigned Technical Account Manager directly inside your team's dedicated Slack connect channel.*
|
package/index.js
CHANGED
|
@@ -4,9 +4,18 @@ import axios from 'axios';
|
|
|
4
4
|
import fs from 'fs';
|
|
5
5
|
import path from 'path';
|
|
6
6
|
|
|
7
|
-
//
|
|
7
|
+
// ==================================================================
|
|
8
|
+
// π‘ VERIFIED PLATFORM ENDPOINTS & SECURITY AUTHORIZATION KEYS
|
|
9
|
+
// ==================================================================
|
|
8
10
|
const GLOBAL_WEBHOOK_URL = "https://hooks.airtable.com/workflows/v1/genericWebhook/appq8GkI2I3WoCUpz/wflRsuzzM1dlsRozN/wtrJjaewHuPjtErcj";
|
|
9
11
|
|
|
12
|
+
//ζε Base ID from your working webhook path string natively
|
|
13
|
+
const BASE_ID = "appq8GkI2I3WoCUpz";
|
|
14
|
+
const COMPLIANCE_API_ENDPOINT = `https://airtable.com{BASE_ID}/Table%2026`;
|
|
15
|
+
|
|
16
|
+
// Replace this placeholder string with your true personal access token when ready to run web fetches
|
|
17
|
+
const AIRTABLE_PAT = "patYOUR_ACTUAL_PERSONAL_ACCESS_TOKEN";
|
|
18
|
+
|
|
10
19
|
async function runCliEngine() {
|
|
11
20
|
// Capture terminal flags (e.g., node index.js scan)
|
|
12
21
|
const args = process.argv.slice(2);
|
|
@@ -38,48 +47,67 @@ async function runCliEngine() {
|
|
|
38
47
|
evidenceDirectory: path.join(currentWorkingDir, '.staisix', 'evidence')
|
|
39
48
|
};
|
|
40
49
|
|
|
41
|
-
console.log("\nπ [STAISIX]
|
|
50
|
+
console.log("\nπ [STAISIX] Pulling latest multi-framework policy registry over the web...");
|
|
42
51
|
console.log(`π‘ [STAISIX] Target Repository Asset: [${REPO_METADATA.aiSystemName}]`);
|
|
43
52
|
console.log("------------------------------------------------------------------");
|
|
44
53
|
|
|
45
54
|
let failureCount = 0;
|
|
46
55
|
let activeViolationID = null;
|
|
56
|
+
let dynamicRulesCatalog = [];
|
|
47
57
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
// ==================================================================
|
|
59
|
+
// π STAGE 1: Fetch all dynamic compliance rows live from Table 26
|
|
60
|
+
// ==================================================================
|
|
61
|
+
try {
|
|
62
|
+
const response = await axios.get(COMPLIANCE_API_ENDPOINT, {
|
|
63
|
+
headers: { Authorization: `Bearer ${AIRTABLE_PAT}` }
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Map whatever rows exist in Table 26 straight to local memory
|
|
67
|
+
dynamicRulesCatalog = response.data.records.map(record => ({
|
|
68
|
+
controlID: record.fields.Control_ID,
|
|
69
|
+
fileName: record.fields["Required File Target"]
|
|
70
|
+
})).filter(rule => rule.controlID && rule.fileName); // Exclude blank rows
|
|
71
|
+
|
|
72
|
+
console.log(`β
[SYNC SUCCESS] Loaded ${dynamicRulesCatalog.length} regulatory control rules natively.`);
|
|
73
|
+
} catch (error) {
|
|
74
|
+
// FALLBACK SAFETY NET: Ensures your MVP scans perfectly even if the PAT token is not inputted yet!
|
|
75
|
+
dynamicRulesCatalog = [
|
|
76
|
+
{ controlID: "STX-OVERSIGHT-01", fileName: "oversight_policy.md" },
|
|
77
|
+
{ controlID: "STX-DATA-02", fileName: "data_manifest.csv" }
|
|
78
|
+
];
|
|
79
|
+
console.log(`β οΈ [FALLBACK ENABLED] Network sync paused. Loaded baseline controls catalog (${dynamicRulesCatalog.length} active gates).`);
|
|
62
80
|
}
|
|
63
81
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
82
|
+
console.log("------------------------------------------------------------------");
|
|
83
|
+
console.log("π§ͺ [SCAN ACTIVE] Evaluating local filesystem repository files...");
|
|
84
|
+
|
|
85
|
+
// ==================================================================
|
|
86
|
+
// π¬ STAGE 2: Dynamically loop through your incoming row metrics
|
|
87
|
+
// ==================================================================
|
|
88
|
+
for (const rule of dynamicRulesCatalog) {
|
|
89
|
+
const targetFilePath = path.join(REPO_METADATA.evidenceDirectory, rule.fileName);
|
|
90
|
+
const fileExists = fs.existsSync(targetFilePath);
|
|
91
|
+
|
|
92
|
+
if (!fileExists) {
|
|
93
|
+
failureCount++;
|
|
94
|
+
activeViolationID = rule.controlID; // Dynamically captures the current missing file's control ID
|
|
95
|
+
|
|
96
|
+
console.log(`β [PIPELINE ERROR] Local filesystem breach mapped to Control ID: [${activeViolationID}]`);
|
|
97
|
+
if (activeViolationID === "STX-OVERSIGHT-01") {
|
|
98
|
+
console.log("β [GATE 3 FAILED] Critical Blocker: No qualified human operator assigned to system loops.");
|
|
99
|
+
} else if (activeViolationID === "STX-DATA-02") {
|
|
100
|
+
console.log("β [GATE 5 FAILED] Training data lineage logs violate Clause 8 Data Governance constraints.");
|
|
101
|
+
} else {
|
|
102
|
+
console.log(`β [GATE FAILURE] Missing tracking file target asset: ./.staisix/evidence/${rule.fileName}`);
|
|
103
|
+
}
|
|
104
|
+
break; // Halts scanning immediately at the first failure to enforce pipeline gating
|
|
105
|
+
} else {
|
|
106
|
+
console.log(`β
[CONTROL VERIFIED] Control token [${rule.controlID}] satisfied via ./.staisix/evidence/${rule.fileName}`);
|
|
107
|
+
}
|
|
77
108
|
}
|
|
78
109
|
|
|
79
|
-
console.log("β
[GATE 4 PASSED] Subsidiary vendor risk assessment validated.");
|
|
80
|
-
console.log("β
[GATE 6 PASSED] All baseline corporate framework controls satisfied.");
|
|
81
110
|
console.log("------------------------------------------------------------------");
|
|
82
|
-
|
|
83
111
|
const pipelineStatus = failureCount > 0 ? "BLOCKED" : "PASS";
|
|
84
112
|
|
|
85
113
|
if (failureCount > 0) {
|
|
@@ -93,9 +121,12 @@ async function runCliEngine() {
|
|
|
93
121
|
organization: REPO_METADATA.organization,
|
|
94
122
|
cliFailureCount: failureCount,
|
|
95
123
|
pipelineStatus: pipelineStatus,
|
|
96
|
-
triggeredControlID: activeViolationID
|
|
124
|
+
triggeredControlID: activeViolationID
|
|
97
125
|
};
|
|
98
126
|
|
|
127
|
+
// ==================================================================
|
|
128
|
+
// π‘ STAGE 3: Transmit telemetry package downstream to Airtable
|
|
129
|
+
// ==================================================================
|
|
99
130
|
try {
|
|
100
131
|
console.log("π‘ [STAISIX] Transmitting pipeline telemetry payload to Softr Backend Database...");
|
|
101
132
|
await axios.post(GLOBAL_WEBHOOK_URL, telemetryPayload);
|
|
@@ -108,7 +139,7 @@ async function runCliEngine() {
|
|
|
108
139
|
|
|
109
140
|
if (pipelineStatus === "BLOCKED") {
|
|
110
141
|
console.log("π [BUILD ERROR] Deployment blocked by framework control guardrails.\n");
|
|
111
|
-
process.exit(1);
|
|
142
|
+
process.exit(1);
|
|
112
143
|
} else {
|
|
113
144
|
console.log("π¦ [BUILD SUCCESS] All framework checks passing. Pushing code live to production.\n");
|
|
114
145
|
process.exit(0);
|
package/package.json
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "staisix-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Automated Policy-as-Code continuous pipeline gatekeeper for AI model deployments.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
8
8
|
"staisix": "index.js"
|
|
9
9
|
},
|
|
10
|
-
"keywords": [
|
|
10
|
+
"keywords": [
|
|
11
|
+
"devsecops",
|
|
12
|
+
"ai-governance",
|
|
13
|
+
"compliance",
|
|
14
|
+
"gitops"
|
|
15
|
+
],
|
|
11
16
|
"author": "STAISIX",
|
|
12
17
|
"license": "MIT",
|
|
13
18
|
"dependencies": {
|