rcf-protocol 1.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/bin/rcf-cli.js +2 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +77 -0
- package/dist/core/ComplianceValidator.d.ts +14 -0
- package/dist/core/ComplianceValidator.js +32 -0
- package/dist/core/MarkerParser.d.ts +13 -0
- package/dist/core/MarkerParser.js +81 -0
- package/dist/core/constants.d.ts +3 -0
- package/dist/core/constants.js +32 -0
- package/dist/core/types.d.ts +26 -0
- package/dist/core/types.js +2 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +11 -0
- package/package.json +36 -0
package/bin/rcf-cli.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const MarkerParser_1 = require("../core/MarkerParser");
|
|
10
|
+
const ComplianceValidator_1 = require("../core/ComplianceValidator");
|
|
11
|
+
const fs_1 = require("fs");
|
|
12
|
+
const path_1 = require("path");
|
|
13
|
+
const pkg = JSON.parse((0, fs_1.readFileSync)((0, path_1.resolve)(__dirname, '../../package.json'), 'utf-8'));
|
|
14
|
+
const program = new commander_1.Command();
|
|
15
|
+
program
|
|
16
|
+
.name('rcf-cli')
|
|
17
|
+
.description('RCF Protocol CLI')
|
|
18
|
+
.version(pkg.version);
|
|
19
|
+
program
|
|
20
|
+
.command('scan [directory]')
|
|
21
|
+
.description('Scan directory for RCF markers')
|
|
22
|
+
.option('-f, --format <type>', 'output format', 'pretty')
|
|
23
|
+
.option('--summary', 'show summary only')
|
|
24
|
+
.action(async (directory = '.', options) => {
|
|
25
|
+
const parser = new MarkerParser_1.MarkerParser();
|
|
26
|
+
const results = await parser.scan(directory);
|
|
27
|
+
if (options.summary) {
|
|
28
|
+
printSummary(results);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
printResults(results, options.format);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
program
|
|
35
|
+
.command('validate [directory]')
|
|
36
|
+
.description('Validate RCF compliance')
|
|
37
|
+
.option('--strict', 'strict mode')
|
|
38
|
+
.action(async (directory = '.', options) => {
|
|
39
|
+
const parser = new MarkerParser_1.MarkerParser();
|
|
40
|
+
const results = await parser.scan(directory);
|
|
41
|
+
const validator = new ComplianceValidator_1.ComplianceValidator({ strict: options.strict });
|
|
42
|
+
const status = await validator.validate(results);
|
|
43
|
+
if (status.valid) {
|
|
44
|
+
console.log(chalk_1.default.green('ā
RCF compliance validated'));
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
console.log(chalk_1.default.red('ā RCF compliance failed'));
|
|
48
|
+
status.errors.forEach(e => console.log(chalk_1.default.red(` ⢠${e.file}:${e.line} - ${e.message}`)));
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
function printSummary(results) {
|
|
53
|
+
const stats = { PUBLIC: 0, PROTECTED: 0, RESTRICTED: 0, NOTICE: 0 };
|
|
54
|
+
results.forEach(r => r.markers.forEach((m) => stats[m.type]++));
|
|
55
|
+
console.log(chalk_1.default.bold('\nš RCF Markers Summary:'));
|
|
56
|
+
console.log(` ${chalk_1.default.green('[RCF:PUBLIC]')}: ${stats.PUBLIC}`);
|
|
57
|
+
console.log(` ${chalk_1.default.yellow('[RCF:PROTECTED]')}: ${stats.PROTECTED}`);
|
|
58
|
+
console.log(` ${chalk_1.default.red('[RCF:RESTRICTED]')}: ${stats.RESTRICTED}`);
|
|
59
|
+
console.log(` ${chalk_1.default.blue('[RCF:NOTICE]')}: ${stats.NOTICE}`);
|
|
60
|
+
console.log(` Total files: ${results.length}\n`);
|
|
61
|
+
}
|
|
62
|
+
function printResults(results, format) {
|
|
63
|
+
if (format === 'json') {
|
|
64
|
+
console.log(JSON.stringify(results, null, 2));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
results.forEach(({ file, markers }) => {
|
|
68
|
+
console.log(chalk_1.default.bold(`\nš ${file}`));
|
|
69
|
+
markers.forEach((m) => {
|
|
70
|
+
const color = m.type === 'PUBLIC' ? 'green' :
|
|
71
|
+
m.type === 'PROTECTED' ? 'yellow' :
|
|
72
|
+
m.type === 'RESTRICTED' ? 'red' : 'blue';
|
|
73
|
+
console.log(` ${chalk_1.default[color](m.marker.name)} Line ${m.line}: ${m.context.substring(0, 50)}...`);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
program.parse();
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ParseResult, ValidationError } from './types';
|
|
2
|
+
interface ValidatorOptions {
|
|
3
|
+
strict?: boolean;
|
|
4
|
+
}
|
|
5
|
+
export declare class ComplianceValidator {
|
|
6
|
+
private strict;
|
|
7
|
+
constructor(options?: ValidatorOptions);
|
|
8
|
+
validate(results: ParseResult[]): Promise<{
|
|
9
|
+
valid: boolean;
|
|
10
|
+
errors: ValidationError[];
|
|
11
|
+
warnings: ValidationError[];
|
|
12
|
+
}>;
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ComplianceValidator = void 0;
|
|
4
|
+
class ComplianceValidator {
|
|
5
|
+
constructor(options = {}) {
|
|
6
|
+
this.strict = options.strict || false;
|
|
7
|
+
}
|
|
8
|
+
async validate(results) {
|
|
9
|
+
const errors = [];
|
|
10
|
+
const warnings = [];
|
|
11
|
+
for (const result of results) {
|
|
12
|
+
const hasNotice = result.markers.some(m => m.type === 'NOTICE');
|
|
13
|
+
const hasProtected = result.markers.some(m => m.type === 'PROTECTED');
|
|
14
|
+
const hasRestricted = result.markers.some(m => m.type === 'RESTRICTED');
|
|
15
|
+
if ((hasProtected || hasRestricted) && !hasNotice) {
|
|
16
|
+
const msg = `File contains PROTECTED/RESTRICTED markers but no [RCF:NOTICE]`;
|
|
17
|
+
if (this.strict) {
|
|
18
|
+
errors.push({ file: result.file, line: 1, message: msg, severity: 'error' });
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
warnings.push({ file: result.file, line: 1, message: msg, severity: 'warning' });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
valid: errors.length === 0,
|
|
27
|
+
errors,
|
|
28
|
+
warnings
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.ComplianceValidator = ComplianceValidator;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ParseResult, ParsedMarker } from './types';
|
|
2
|
+
interface ParserOptions {
|
|
3
|
+
extensions?: string[];
|
|
4
|
+
ignore?: string[];
|
|
5
|
+
}
|
|
6
|
+
export declare class MarkerParser {
|
|
7
|
+
private extensions;
|
|
8
|
+
private ignore;
|
|
9
|
+
constructor(options?: ParserOptions);
|
|
10
|
+
scan(directory: string): Promise<ParseResult[]>;
|
|
11
|
+
parseFile(filePath: string): Promise<ParsedMarker[]>;
|
|
12
|
+
}
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.MarkerParser = void 0;
|
|
37
|
+
const fs = __importStar(require("fs/promises"));
|
|
38
|
+
const glob_1 = require("glob");
|
|
39
|
+
const constants_1 = require("./constants");
|
|
40
|
+
class MarkerParser {
|
|
41
|
+
constructor(options = {}) {
|
|
42
|
+
this.extensions = options.extensions || ['.ts', '.js', '.tsx', '.jsx', '.py'];
|
|
43
|
+
this.ignore = options.ignore || ['node_modules/**', 'dist/**', '.git/**'];
|
|
44
|
+
}
|
|
45
|
+
async scan(directory) {
|
|
46
|
+
const pattern = `**/*{${this.extensions.join(',')}}`;
|
|
47
|
+
const files = await (0, glob_1.glob)(pattern, {
|
|
48
|
+
cwd: directory,
|
|
49
|
+
ignore: this.ignore,
|
|
50
|
+
absolute: true
|
|
51
|
+
});
|
|
52
|
+
const results = [];
|
|
53
|
+
for (const file of files) {
|
|
54
|
+
const markers = await this.parseFile(file);
|
|
55
|
+
if (markers.length > 0) {
|
|
56
|
+
results.push({ file, markers });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return results;
|
|
60
|
+
}
|
|
61
|
+
async parseFile(filePath) {
|
|
62
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
63
|
+
const lines = content.split('\n');
|
|
64
|
+
const markers = [];
|
|
65
|
+
lines.forEach((line, index) => {
|
|
66
|
+
const matches = line.matchAll(constants_1.MARKER_REGEX);
|
|
67
|
+
for (const match of matches) {
|
|
68
|
+
const type = match[1];
|
|
69
|
+
markers.push({
|
|
70
|
+
type,
|
|
71
|
+
marker: constants_1.RCF_MARKERS[type],
|
|
72
|
+
line: index + 1,
|
|
73
|
+
column: match.index || 0,
|
|
74
|
+
context: line.trim()
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
return markers;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
exports.MarkerParser = MarkerParser;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MARKER_REGEX = exports.RCF_MARKERS = void 0;
|
|
4
|
+
exports.RCF_MARKERS = {
|
|
5
|
+
PUBLIC: {
|
|
6
|
+
name: '[RCF:PUBLIC]',
|
|
7
|
+
level: 0,
|
|
8
|
+
description: 'Architecture and public concepts. Safe to discuss.',
|
|
9
|
+
permissions: ['read', 'study', 'audit', 'discuss']
|
|
10
|
+
},
|
|
11
|
+
PROTECTED: {
|
|
12
|
+
name: '[RCF:PROTECTED]',
|
|
13
|
+
level: 1,
|
|
14
|
+
description: 'Core methodology. Visible but not replicable.',
|
|
15
|
+
permissions: ['read', 'study', 'audit'],
|
|
16
|
+
restrictions: ['no-replication', 'no-automation', 'no-ml-training']
|
|
17
|
+
},
|
|
18
|
+
RESTRICTED: {
|
|
19
|
+
name: '[RCF:RESTRICTED]',
|
|
20
|
+
level: 2,
|
|
21
|
+
description: 'Highly sensitive implementation. Minimal rights.',
|
|
22
|
+
permissions: ['read'],
|
|
23
|
+
restrictions: ['no-replication', 'no-automation', 'no-ml-training', 'no-modification']
|
|
24
|
+
},
|
|
25
|
+
NOTICE: {
|
|
26
|
+
name: '[RCF:NOTICE]',
|
|
27
|
+
level: 'meta',
|
|
28
|
+
description: 'Triggers requirement for adjacent legal notice.',
|
|
29
|
+
action: 'require-notice'
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
exports.MARKER_REGEX = /\[RCF:(PUBLIC|PROTECTED|RESTRICTED|NOTICE)\]/g;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type RCFMarkerType = 'PUBLIC' | 'PROTECTED' | 'RESTRICTED' | 'NOTICE';
|
|
2
|
+
export interface RCFMarker {
|
|
3
|
+
name: string;
|
|
4
|
+
level: number | 'meta';
|
|
5
|
+
description: string;
|
|
6
|
+
permissions?: string[];
|
|
7
|
+
restrictions?: string[];
|
|
8
|
+
action?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface ParsedMarker {
|
|
11
|
+
type: RCFMarkerType;
|
|
12
|
+
marker: RCFMarker;
|
|
13
|
+
line: number;
|
|
14
|
+
column: number;
|
|
15
|
+
context: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ParseResult {
|
|
18
|
+
file: string;
|
|
19
|
+
markers: ParsedMarker[];
|
|
20
|
+
}
|
|
21
|
+
export interface ValidationError {
|
|
22
|
+
file: string;
|
|
23
|
+
line: number;
|
|
24
|
+
message: string;
|
|
25
|
+
severity: 'error' | 'warning';
|
|
26
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { MarkerParser } from './core/MarkerParser';
|
|
2
|
+
export { ComplianceValidator } from './core/ComplianceValidator';
|
|
3
|
+
export { RCF_MARKERS, MARKER_REGEX } from './core/constants';
|
|
4
|
+
export { RCFMarker, RCFMarkerType, ParseResult } from './core/types';
|
|
5
|
+
export declare const VERSION = "1.1.0";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.VERSION = exports.MARKER_REGEX = exports.RCF_MARKERS = exports.ComplianceValidator = exports.MarkerParser = void 0;
|
|
4
|
+
var MarkerParser_1 = require("./core/MarkerParser");
|
|
5
|
+
Object.defineProperty(exports, "MarkerParser", { enumerable: true, get: function () { return MarkerParser_1.MarkerParser; } });
|
|
6
|
+
var ComplianceValidator_1 = require("./core/ComplianceValidator");
|
|
7
|
+
Object.defineProperty(exports, "ComplianceValidator", { enumerable: true, get: function () { return ComplianceValidator_1.ComplianceValidator; } });
|
|
8
|
+
var constants_1 = require("./core/constants");
|
|
9
|
+
Object.defineProperty(exports, "RCF_MARKERS", { enumerable: true, get: function () { return constants_1.RCF_MARKERS; } });
|
|
10
|
+
Object.defineProperty(exports, "MARKER_REGEX", { enumerable: true, get: function () { return constants_1.MARKER_REGEX; } });
|
|
11
|
+
exports.VERSION = '1.1.0';
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "rcf-protocol",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "RCF Protocol SDK for TypeScript/JavaScript",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"rcf-cli": "bin/rcf-cli.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"bin"
|
|
13
|
+
],
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/aliyevaladddin/rcf-protocol.git"
|
|
17
|
+
},
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc",
|
|
21
|
+
"dev": "ts-node src/cli/index.ts",
|
|
22
|
+
"clean": "rm -rf dist",
|
|
23
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"chalk": "^4.1.2",
|
|
27
|
+
"commander": "^11.1.0",
|
|
28
|
+
"glob": "^10.3.10"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/glob": "^8.1.0",
|
|
32
|
+
"@types/node": "^20.10.0",
|
|
33
|
+
"ts-node": "^10.9.0",
|
|
34
|
+
"typescript": "^5.3.0"
|
|
35
|
+
}
|
|
36
|
+
}
|