@asterpay/attest-sdk 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.
Files changed (45) hide show
  1. package/dist/ai-packages.d.ts +9 -0
  2. package/dist/ai-packages.d.ts.map +1 -0
  3. package/dist/ai-packages.js +62 -0
  4. package/dist/ai-packages.js.map +1 -0
  5. package/dist/attest.d.ts +28 -0
  6. package/dist/attest.d.ts.map +1 -0
  7. package/dist/attest.js +92 -0
  8. package/dist/attest.js.map +1 -0
  9. package/dist/audit-logger.d.ts +34 -0
  10. package/dist/audit-logger.d.ts.map +1 -0
  11. package/dist/audit-logger.js +116 -0
  12. package/dist/audit-logger.js.map +1 -0
  13. package/dist/compliance-checker.d.ts +3 -0
  14. package/dist/compliance-checker.d.ts.map +1 -0
  15. package/dist/compliance-checker.js +109 -0
  16. package/dist/compliance-checker.js.map +1 -0
  17. package/dist/docs-generator.d.ts +12 -0
  18. package/dist/docs-generator.d.ts.map +1 -0
  19. package/dist/docs-generator.js +143 -0
  20. package/dist/docs-generator.js.map +1 -0
  21. package/dist/index.d.ts +12 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +9 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/risk-classifier.d.ts +8 -0
  26. package/dist/risk-classifier.d.ts.map +1 -0
  27. package/dist/risk-classifier.js +95 -0
  28. package/dist/risk-classifier.js.map +1 -0
  29. package/dist/scanner.d.ts +6 -0
  30. package/dist/scanner.d.ts.map +1 -0
  31. package/dist/scanner.js +151 -0
  32. package/dist/scanner.js.map +1 -0
  33. package/dist/scanner.test.d.ts +2 -0
  34. package/dist/scanner.test.d.ts.map +1 -0
  35. package/dist/scanner.test.js +21 -0
  36. package/dist/scanner.test.js.map +1 -0
  37. package/dist/transparency.d.ts +5 -0
  38. package/dist/transparency.d.ts.map +1 -0
  39. package/dist/transparency.js +39 -0
  40. package/dist/transparency.js.map +1 -0
  41. package/dist/types.d.ts +63 -0
  42. package/dist/types.d.ts.map +1 -0
  43. package/dist/types.js +2 -0
  44. package/dist/types.js.map +1 -0
  45. package/package.json +47 -0
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Known AI / LLM SDK package names (npm import specifiers, without version).
3
+ * Extend as ecosystem evolves.
4
+ */
5
+ export declare const AI_SDK_PACKAGES: readonly string[];
6
+ /** Patterns in source text that suggest prohibited / high-risk use cases (heuristic). */
7
+ export declare const HIGH_RISK_KEYWORDS: readonly ["credit score", "credit scoring", "loan approval", "recruitment", "hiring decision", "biometric", "facial recognition", "emotion recognition", "social scoring", "manipulation", "subliminal"];
8
+ export declare const PROHIBITED_KEYWORDS: readonly ["social scoring", "subliminal", "manipulative techniques", "real-time remote biometric"];
9
+ //# sourceMappingURL=ai-packages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-packages.d.ts","sourceRoot":"","sources":["../src/ai-packages.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,SAAS,MAAM,EAoC5C,CAAC;AAEF,yFAAyF;AACzF,eAAO,MAAM,kBAAkB,0MAYrB,CAAC;AAEX,eAAO,MAAM,mBAAmB,oGAKtB,CAAC"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Known AI / LLM SDK package names (npm import specifiers, without version).
3
+ * Extend as ecosystem evolves.
4
+ */
5
+ export const AI_SDK_PACKAGES = [
6
+ 'openai',
7
+ '@anthropic-ai/sdk',
8
+ '@google/generative-ai',
9
+ '@google-cloud/aiplatform',
10
+ '@google-cloud/vertexai',
11
+ '@azure/openai',
12
+ '@aws-sdk/client-bedrock-runtime',
13
+ 'cohere-ai',
14
+ '@mistralai/mistralai',
15
+ 'replicate',
16
+ '@huggingface/inference',
17
+ 'langchain',
18
+ '@langchain/core',
19
+ '@langchain/openai',
20
+ 'ai',
21
+ '@ai-sdk/openai',
22
+ '@ai-sdk/anthropic',
23
+ '@ai-sdk/google',
24
+ 'groq-sdk',
25
+ '@xenova/transformers',
26
+ 'ollama',
27
+ 'together-ai',
28
+ '@deepgram/sdk',
29
+ 'assemblyai',
30
+ 'elevenlabs',
31
+ 'anthropic',
32
+ 'vertexai',
33
+ 'openai-edge',
34
+ '@openai/agents',
35
+ 'voyageai',
36
+ 'pinecone-client',
37
+ '@pinecone-database/pinecone',
38
+ 'weaviate-ts-client',
39
+ 'chromadb',
40
+ '@qdrant/js-client-rest',
41
+ ];
42
+ /** Patterns in source text that suggest prohibited / high-risk use cases (heuristic). */
43
+ export const HIGH_RISK_KEYWORDS = [
44
+ 'credit score',
45
+ 'credit scoring',
46
+ 'loan approval',
47
+ 'recruitment',
48
+ 'hiring decision',
49
+ 'biometric',
50
+ 'facial recognition',
51
+ 'emotion recognition',
52
+ 'social scoring',
53
+ 'manipulation',
54
+ 'subliminal',
55
+ ];
56
+ export const PROHIBITED_KEYWORDS = [
57
+ 'social scoring',
58
+ 'subliminal',
59
+ 'manipulative techniques',
60
+ 'real-time remote biometric',
61
+ ];
62
+ //# sourceMappingURL=ai-packages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-packages.js","sourceRoot":"","sources":["../src/ai-packages.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAsB;IAChD,QAAQ;IACR,mBAAmB;IACnB,uBAAuB;IACvB,0BAA0B;IAC1B,wBAAwB;IACxB,eAAe;IACf,iCAAiC;IACjC,WAAW;IACX,sBAAsB;IACtB,WAAW;IACX,wBAAwB;IACxB,WAAW;IACX,iBAAiB;IACjB,mBAAmB;IACnB,IAAI;IACJ,gBAAgB;IAChB,mBAAmB;IACnB,gBAAgB;IAChB,UAAU;IACV,sBAAsB;IACtB,QAAQ;IACR,aAAa;IACb,eAAe;IACf,YAAY;IACZ,YAAY;IACZ,WAAW;IACX,UAAU;IACV,aAAa;IACb,gBAAgB;IAChB,UAAU;IACV,iBAAiB;IACjB,6BAA6B;IAC7B,oBAAoB;IACpB,UAAU;IACV,wBAAwB;CACzB,CAAC;AAEF,yFAAyF;AACzF,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,cAAc;IACd,gBAAgB;IAChB,eAAe;IACf,aAAa;IACb,iBAAiB;IACjB,WAAW;IACX,oBAAoB;IACpB,qBAAqB;IACrB,gBAAgB;IAChB,cAAc;IACd,YAAY;CACJ,CAAC;AAEX,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,gBAAgB;IAChB,YAAY;IACZ,yBAAyB;IACzB,4BAA4B;CACpB,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { type DisclosureLocale } from './transparency.js';
2
+ import type { AttestConfig, ComplianceReport, ExportAuditOptions, GenerateDocsOptions, RiskClassification, ScanResult, TrackMeta } from './types.js';
3
+ export declare class Attest {
4
+ private readonly config;
5
+ private readonly projectRoot;
6
+ private readonly audit?;
7
+ constructor(config: AttestConfig);
8
+ scan(): ScanResult;
9
+ classifyRisk(): Promise<RiskClassification>;
10
+ check(): ComplianceReport;
11
+ generateDocs(options: GenerateDocsOptions): Promise<{
12
+ files: string[];
13
+ }>;
14
+ exportAuditLog(options: ExportAuditOptions): string;
15
+ disclosure(locale?: DisclosureLocale, opts?: {
16
+ humanAvailable?: boolean;
17
+ }): string;
18
+ /**
19
+ * Wrap an async AI call with audit logging (duration, optional meta).
20
+ */
21
+ track<T>(fn: () => Promise<T>, meta?: TrackMeta): Promise<T>;
22
+ verifyAuditChain(): {
23
+ ok: boolean;
24
+ brokenAt?: number;
25
+ };
26
+ }
27
+ export declare function defaultAuditPath(projectRoot: string): string;
28
+ //# sourceMappingURL=attest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attest.d.ts","sourceRoot":"","sources":["../src/attest.ts"],"names":[],"mappings":"AAMA,OAAO,EAAiB,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,UAAU,EACV,SAAS,EACV,MAAM,YAAY,CAAC;AAEpB,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAc;gBAEzB,MAAM,EAAE,YAAY;IAUhC,IAAI,IAAI,UAAU;IAIZ,YAAY,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAKjD,KAAK,IAAI,gBAAgB;IAKnB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAY9E,cAAc,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM;IASnD,UAAU,CAAC,MAAM,GAAE,gBAAuB,EAAE,IAAI,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,MAAM;IAIxF;;OAEG;IACG,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC;IA6BlE,gBAAgB,IAAI;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE;CAGvD;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE5D"}
package/dist/attest.js ADDED
@@ -0,0 +1,92 @@
1
+ import * as path from 'node:path';
2
+ import { AuditLogger } from './audit-logger.js';
3
+ import { checkCompliance } from './compliance-checker.js';
4
+ import { classifyRisk } from './risk-classifier.js';
5
+ import { generateAnnexIvDocs } from './docs-generator.js';
6
+ import { scanProject } from './scanner.js';
7
+ import { getDisclosure } from './transparency.js';
8
+ export class Attest {
9
+ config;
10
+ projectRoot;
11
+ audit;
12
+ constructor(config) {
13
+ this.config = config;
14
+ this.projectRoot = path.resolve(config.projectRoot ?? process.cwd());
15
+ const logPath = config.auditLogPath ?? path.join(this.projectRoot, '.attest', 'audit.jsonl');
16
+ this.audit = new AuditLogger(logPath, config.system.name);
17
+ }
18
+ scan() {
19
+ return scanProject({ rootDir: this.projectRoot });
20
+ }
21
+ async classifyRisk() {
22
+ const scan = this.scan();
23
+ return classifyRisk(scan);
24
+ }
25
+ check() {
26
+ const scan = this.scan();
27
+ return checkCompliance(scan, this.projectRoot);
28
+ }
29
+ async generateDocs(options) {
30
+ const scan = this.scan();
31
+ const risk = classifyRisk(scan);
32
+ return generateAnnexIvDocs(scan, risk, {
33
+ outputDir: options.outputDir,
34
+ systemName: this.config.system.name,
35
+ provider: this.config.system.provider,
36
+ description: this.config.system.description,
37
+ language: options.language,
38
+ });
39
+ }
40
+ exportAuditLog(options) {
41
+ if (!this.audit)
42
+ return '';
43
+ const entries = this.audit.exportJson(options.from);
44
+ if (options.format === 'jsonl') {
45
+ return entries.map((e) => JSON.stringify(e)).join('\n') + '\n';
46
+ }
47
+ return JSON.stringify(entries, null, 2) + '\n';
48
+ }
49
+ disclosure(locale = 'en', opts) {
50
+ return getDisclosure(locale, opts);
51
+ }
52
+ /**
53
+ * Wrap an async AI call with audit logging (duration, optional meta).
54
+ */
55
+ async track(fn, meta) {
56
+ if (!this.audit)
57
+ return fn();
58
+ const start = Date.now();
59
+ try {
60
+ const result = await fn();
61
+ const ms = Date.now() - start;
62
+ this.audit.append({
63
+ action: 'ai_inference',
64
+ model: meta?.model,
65
+ purpose: meta?.purpose,
66
+ input_type: 'text',
67
+ contains_pii: meta?.containsPII ?? false,
68
+ human_oversight: meta?.humanOversight ?? 'none',
69
+ response_time_ms: ms,
70
+ });
71
+ return result;
72
+ }
73
+ catch (err) {
74
+ const ms = Date.now() - start;
75
+ this.audit.append({
76
+ action: 'ai_inference_error',
77
+ model: meta?.model,
78
+ purpose: meta?.purpose,
79
+ response_time_ms: ms,
80
+ error: err instanceof Error ? err.message : String(err),
81
+ });
82
+ throw err;
83
+ }
84
+ }
85
+ verifyAuditChain() {
86
+ return this.audit?.verifyChain() ?? { ok: true };
87
+ }
88
+ }
89
+ export function defaultAuditPath(projectRoot) {
90
+ return path.join(projectRoot, '.attest', 'audit.jsonl');
91
+ }
92
+ //# sourceMappingURL=attest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attest.js","sourceRoot":"","sources":["../src/attest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ export interface AuditEntry {
2
+ id: string;
3
+ timestamp: string;
4
+ system: string;
5
+ action: string;
6
+ model?: string;
7
+ purpose?: string;
8
+ input_type?: string;
9
+ contains_pii?: boolean;
10
+ human_oversight?: string;
11
+ response_time_ms?: number;
12
+ tokens_used?: number;
13
+ error?: string;
14
+ hash: string;
15
+ previous_hash: string | null;
16
+ }
17
+ export declare class AuditLogger {
18
+ private readonly logPath;
19
+ private readonly systemName;
20
+ private lastHash;
21
+ constructor(logPath: string, systemName: string);
22
+ private loadLastHash;
23
+ /** `system` is always taken from the logger instance — do not pass it in `partial`. */
24
+ append(partial: Omit<AuditEntry, 'id' | 'timestamp' | 'hash' | 'previous_hash' | 'system'> & {
25
+ action: string;
26
+ }): AuditEntry;
27
+ readAll(): AuditEntry[];
28
+ exportJson(fromIso?: string): AuditEntry[];
29
+ verifyChain(): {
30
+ ok: boolean;
31
+ brokenAt?: number;
32
+ };
33
+ }
34
+ //# sourceMappingURL=audit-logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-logger.d.ts","sourceRoot":"","sources":["../src/audit-logger.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAwBD,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAuB;gBAE3B,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;IAM/C,OAAO,CAAC,YAAY;IAkBpB,uFAAuF;IACvF,MAAM,CACJ,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,WAAW,GAAG,MAAM,GAAG,eAAe,GAAG,QAAQ,CAAC,GAAG;QACpF,MAAM,EAAE,MAAM,CAAC;KAChB,GACA,UAAU;IAmBb,OAAO,IAAI,UAAU,EAAE;IAUvB,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE;IAO1C,WAAW,IAAI;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE;CA4BlD"}
@@ -0,0 +1,116 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { createHash, randomUUID } from 'node:crypto';
4
+ function sha256Hex(input) {
5
+ return createHash('sha256').update(input, 'utf8').digest('hex');
6
+ }
7
+ function serializeForHash(entry) {
8
+ return JSON.stringify({
9
+ id: entry.id,
10
+ timestamp: entry.timestamp,
11
+ system: entry.system,
12
+ action: entry.action,
13
+ model: entry.model,
14
+ purpose: entry.purpose,
15
+ input_type: entry.input_type,
16
+ contains_pii: entry.contains_pii,
17
+ human_oversight: entry.human_oversight,
18
+ response_time_ms: entry.response_time_ms,
19
+ tokens_used: entry.tokens_used,
20
+ error: entry.error,
21
+ previous_hash: entry.previous_hash,
22
+ });
23
+ }
24
+ export class AuditLogger {
25
+ logPath;
26
+ systemName;
27
+ lastHash = null;
28
+ constructor(logPath, systemName) {
29
+ this.logPath = path.resolve(logPath);
30
+ this.systemName = systemName;
31
+ this.loadLastHash();
32
+ }
33
+ loadLastHash() {
34
+ if (!fs.existsSync(this.logPath)) {
35
+ this.lastHash = null;
36
+ return;
37
+ }
38
+ const lines = fs.readFileSync(this.logPath, 'utf8').trim().split('\n').filter(Boolean);
39
+ if (lines.length === 0) {
40
+ this.lastHash = null;
41
+ return;
42
+ }
43
+ try {
44
+ const last = JSON.parse(lines[lines.length - 1]);
45
+ this.lastHash = last.hash;
46
+ }
47
+ catch {
48
+ this.lastHash = null;
49
+ }
50
+ }
51
+ /** `system` is always taken from the logger instance — do not pass it in `partial`. */
52
+ append(partial) {
53
+ const id = `log_${randomUUID()}`;
54
+ const timestamp = new Date().toISOString();
55
+ const previous_hash = this.lastHash;
56
+ const base = {
57
+ ...partial,
58
+ id,
59
+ timestamp,
60
+ system: this.systemName,
61
+ previous_hash,
62
+ };
63
+ const hash = sha256Hex(serializeForHash(base));
64
+ const entry = { ...base, hash };
65
+ fs.mkdirSync(path.dirname(this.logPath), { recursive: true });
66
+ fs.appendFileSync(this.logPath, JSON.stringify(entry) + '\n', 'utf8');
67
+ this.lastHash = hash;
68
+ return entry;
69
+ }
70
+ readAll() {
71
+ if (!fs.existsSync(this.logPath))
72
+ return [];
73
+ return fs
74
+ .readFileSync(this.logPath, 'utf8')
75
+ .trim()
76
+ .split('\n')
77
+ .filter(Boolean)
78
+ .map((line) => JSON.parse(line));
79
+ }
80
+ exportJson(fromIso) {
81
+ const all = this.readAll();
82
+ if (!fromIso)
83
+ return all;
84
+ const from = Date.parse(fromIso);
85
+ return all.filter((e) => Date.parse(e.timestamp) >= from);
86
+ }
87
+ verifyChain() {
88
+ const all = this.readAll();
89
+ let prev = null;
90
+ for (let i = 0; i < all.length; i++) {
91
+ const e = all[i];
92
+ if (e.previous_hash !== prev)
93
+ return { ok: false, brokenAt: i };
94
+ const expected = sha256Hex(serializeForHash({
95
+ id: e.id,
96
+ timestamp: e.timestamp,
97
+ system: e.system,
98
+ action: e.action,
99
+ model: e.model,
100
+ purpose: e.purpose,
101
+ input_type: e.input_type,
102
+ contains_pii: e.contains_pii,
103
+ human_oversight: e.human_oversight,
104
+ response_time_ms: e.response_time_ms,
105
+ tokens_used: e.tokens_used,
106
+ error: e.error,
107
+ previous_hash: e.previous_hash,
108
+ }));
109
+ if (expected !== e.hash)
110
+ return { ok: false, brokenAt: i };
111
+ prev = e.hash;
112
+ }
113
+ return { ok: true };
114
+ }
115
+ }
116
+ //# sourceMappingURL=audit-logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-logger.js","sourceRoot":"","sources":["../src/audit-logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ComplianceReport, ScanResult } from './types.js';
2
+ export declare function checkCompliance(scan: ScanResult, rootDir?: string): ComplianceReport;
3
+ //# sourceMappingURL=compliance-checker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compliance-checker.d.ts","sourceRoot":"","sources":["../src/compliance-checker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAmB,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AA+DhF,wBAAgB,eAAe,CAC7B,IAAI,EAAE,UAAU,EAChB,OAAO,GAAE,MAAqB,GAC7B,gBAAgB,CAuDlB"}
@@ -0,0 +1,109 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ const TRANSPARENCY_PATTERNS = [
4
+ /artificial intelligence/i,
5
+ /\bai[-\s]generated\b/i,
6
+ /\bthis (chat|conversation|message) (is|was) (powered|created) by\b/i,
7
+ /powered by ai/i,
8
+ /@asterpay\/attest/i,
9
+ /attest\.disclosure/i,
10
+ /eu ai act/i,
11
+ ];
12
+ const LOGGING_PATTERNS = [
13
+ /@asterpay\/attest-sdk/i,
14
+ /attest\.track/i,
15
+ /audit.?log/i,
16
+ /compliance.?log/i,
17
+ ];
18
+ const OVERSIGHT_PATTERNS = [
19
+ /human.?in.?the.?loop/i,
20
+ /human.?oversight/i,
21
+ /humanOversight/i,
22
+ /requireApproval/i,
23
+ /approval.?gate/i,
24
+ ];
25
+ function readProjectCorpus(rootDir, maxBytes = 1_500_000) {
26
+ const chunks = [];
27
+ let total = 0;
28
+ const walk = (dir) => {
29
+ let entries;
30
+ try {
31
+ entries = fs.readdirSync(dir, { withFileTypes: true });
32
+ }
33
+ catch {
34
+ return;
35
+ }
36
+ for (const e of entries) {
37
+ if (e.name === 'node_modules' ||
38
+ e.name === '.git' ||
39
+ e.name === 'dist' ||
40
+ e.name === '.next')
41
+ continue;
42
+ const full = path.join(dir, e.name);
43
+ if (e.isDirectory())
44
+ walk(full);
45
+ else if (/\.(ts|tsx|js|jsx|mdx?|vue|svelte)$/i.test(e.name)) {
46
+ try {
47
+ const buf = fs.readFileSync(full);
48
+ if (total + buf.length > maxBytes)
49
+ return;
50
+ total += buf.length;
51
+ chunks.push(buf.toString('utf8'));
52
+ }
53
+ catch {
54
+ /* ignore */
55
+ }
56
+ }
57
+ }
58
+ };
59
+ walk(rootDir);
60
+ return chunks.join('\n');
61
+ }
62
+ export function checkCompliance(scan, rootDir = scan.rootDir) {
63
+ const corpus = readProjectCorpus(rootDir);
64
+ const checks = [];
65
+ const hasAi = scan.packagesDetected.length > 0;
66
+ checks.push({
67
+ id: 'ai-usage',
68
+ label: 'AI SDK usage detected',
69
+ status: hasAi ? 'pass' : 'warn',
70
+ detail: hasAi
71
+ ? `Packages: ${scan.packagesDetected.join(', ')}`
72
+ : 'No known AI SDK imports found (may still use REST or other paths).',
73
+ });
74
+ const transparency = TRANSPARENCY_PATTERNS.some((re) => re.test(corpus));
75
+ checks.push({
76
+ id: 'transparency',
77
+ label: 'Transparency / disclosure signals',
78
+ status: hasAi ? (transparency ? 'pass' : 'fail') : 'warn',
79
+ detail: transparency
80
+ ? 'Found disclosure-related patterns in source.'
81
+ : hasAi
82
+ ? 'No obvious user-facing AI disclosure pattern detected — Article 50 style transparency may be required.'
83
+ : 'N/A without AI usage.',
84
+ });
85
+ const logging = LOGGING_PATTERNS.some((re) => re.test(corpus));
86
+ checks.push({
87
+ id: 'logging',
88
+ label: 'Logging / attest integration signals',
89
+ status: hasAi ? (logging ? 'pass' : 'warn') : 'warn',
90
+ detail: logging
91
+ ? 'Found logging or @asterpay/attest usage hints.'
92
+ : 'Consider structured logging for AI inferences (Article 12 style record-keeping for high-risk systems).',
93
+ });
94
+ const oversight = OVERSIGHT_PATTERNS.some((re) => re.test(corpus));
95
+ checks.push({
96
+ id: 'oversight',
97
+ label: 'Human oversight signals',
98
+ status: hasAi ? (oversight ? 'pass' : 'warn') : 'warn',
99
+ detail: oversight
100
+ ? 'Found human oversight related patterns.'
101
+ : 'No human oversight patterns detected — may be required for high-risk deployments (Article 14).',
102
+ });
103
+ const pass = checks.filter((c) => c.status === 'pass').length;
104
+ const fail = checks.filter((c) => c.status === 'fail').length;
105
+ const warn = checks.filter((c) => c.status === 'warn').length;
106
+ const score = Math.max(0, Math.min(100, Math.round((pass * 100 - fail * 25 - warn * 10) / checks.length)));
107
+ return { checks, score };
108
+ }
109
+ //# sourceMappingURL=compliance-checker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compliance-checker.js","sourceRoot":"","sources":["../src/compliance-checker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { RiskClassification, ScanResult } from './types.js';
2
+ export interface GenerateAnnexIvOptions {
3
+ outputDir: string;
4
+ systemName: string;
5
+ provider: string;
6
+ description?: string;
7
+ language?: string;
8
+ }
9
+ export declare function generateAnnexIvDocs(scan: ScanResult, risk: RiskClassification, opts: GenerateAnnexIvOptions): {
10
+ files: string[];
11
+ };
12
+ //# sourceMappingURL=docs-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs-generator.d.ts","sourceRoot":"","sources":["../src/docs-generator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEjE,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAMD,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,kBAAkB,EACxB,IAAI,EAAE,sBAAsB,GAC3B;IAAE,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CA8IrB"}
@@ -0,0 +1,143 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ function mdEscape(s) {
4
+ return s.replace(/\|/g, '\\|');
5
+ }
6
+ export function generateAnnexIvDocs(scan, risk, opts) {
7
+ const out = path.resolve(opts.outputDir);
8
+ fs.mkdirSync(out, { recursive: true });
9
+ const lang = opts.language ?? 'en';
10
+ const files = [];
11
+ const technical = `---
12
+ title: Technical Documentation (Annex IV style outline)
13
+ language: ${lang}
14
+ generated_by: "@asterpay/attest-sdk"
15
+ ---
16
+
17
+ # Technical documentation — ${mdEscape(opts.systemName)}
18
+
19
+ > **Disclaimer:** This is a developer-generated scaffold to support EU AI Act documentation work. It is **not** legal advice and does not replace conformity assessment or counsel.
20
+
21
+ ## 1. General description
22
+
23
+ | Field | Value |
24
+ |-------|-------|
25
+ | System name | ${mdEscape(opts.systemName)} |
26
+ | Provider / deployer | ${mdEscape(opts.provider)} |
27
+ | Description | ${mdEscape(opts.description ?? '—')} |
28
+ | Scanned root | \`${mdEscape(scan.rootDir)}\` |
29
+ | Files scanned | ${scan.filesScanned} |
30
+
31
+ ## 2. Intended purpose
32
+
33
+ Describe the intended purpose, end-users, and context of deployment. (Fill manually.)
34
+
35
+ ## 3. AI components detected (automated scan)
36
+
37
+ The following third-party AI-related packages were detected from import analysis:
38
+
39
+ ${scan.packagesDetected.length ? scan.packagesDetected.map((p) => `- \`${mdEscape(p)}\``).join('\n') : '_None detected — verify REST/SDK usage not covered by static scan._'}
40
+
41
+ ### Findings detail
42
+
43
+ | Package | File | Line | Kind |
44
+ |---------|------|------|------|
45
+ ${scan.findings.length ? scan.findings.map((f) => `| ${mdEscape(f.packageName)} | ${mdEscape(f.filePath)} | ${f.line} | ${f.kind} |`).join('\n') : '| — | — | — | — |'}
46
+
47
+ ## 4. Risk classification (heuristic)
48
+
49
+ | Field | Value |
50
+ |-------|-------|
51
+ | Level | **${risk.level}** |
52
+ | Rationale | ${mdEscape(risk.reason)} |
53
+ | Relevant articles (indicative) | ${risk.articles.join(', ') || '—'} |
54
+
55
+ ### Warnings
56
+
57
+ ${risk.warnings.length ? risk.warnings.map((w) => `- ${mdEscape(w)}`).join('\n') : '_None_'}
58
+
59
+ ## 5. Data governance (Article 10) — template
60
+
61
+ - Training data: _N/A / describe_
62
+ - Input data: _describe categories, retention, minimisation_
63
+ - Data quality measures: _describe_
64
+
65
+ ## 6. Record-keeping & logging (Article 12) — template
66
+
67
+ - Log fields: model, purpose, timestamps, human oversight flags, PII flags.
68
+ - Retention policy: _define_
69
+ - Tamper-evidence: use \`@asterpay/attest-sdk\` audit log hash chain where applicable.
70
+
71
+ ## 7. Transparency (Article 13 / limited-risk) — template
72
+
73
+ - User-facing disclosures: _link to UI copy_
74
+ - Machine-readable metadata: _optional_
75
+
76
+ ## 8. Human oversight (Article 14) — template
77
+
78
+ - Override mechanisms: _describe_
79
+ - Human review workflows: _describe_
80
+
81
+ ## 9. Accuracy, robustness, cybersecurity (Article 15) — template
82
+
83
+ - Testing strategy: _describe_
84
+ - Monitoring: _describe_
85
+ - Incident process: _describe_
86
+
87
+ ## 10. Conformity & registration
88
+
89
+ - Conformity assessment route: _self / third-party_
90
+ - EU database registration: _status / ID_
91
+
92
+ ---
93
+
94
+ _Generated by Attest — Powered by AsterPay._
95
+ `;
96
+ const riskMd = `---
97
+ title: Risk assessment (working draft)
98
+ ---
99
+
100
+ # Risk assessment — ${mdEscape(opts.systemName)}
101
+
102
+ ## Summary
103
+
104
+ - **Heuristic risk level:** ${risk.level}
105
+ - **Reason:** ${mdEscape(risk.reason)}
106
+
107
+ ## Risk management system (Article 9)
108
+
109
+ Document identification, analysis, evaluation, and mitigation of risks throughout the lifecycle. (Fill manually.)
110
+
111
+ ## Post-market monitoring
112
+
113
+ Describe monitoring, feedback loops, and update policy. (Fill manually.)
114
+ `;
115
+ const decl = `---
116
+ title: EU Declaration of Conformity (template)
117
+ ---
118
+
119
+ # EU Declaration of Conformity — template
120
+
121
+ > Complete with legal review. This file is a non-binding placeholder.
122
+
123
+ 1. AI system name: **${mdEscape(opts.systemName)}**
124
+ 2. Provider: **${mdEscape(opts.provider)}**
125
+ 3. The AI system complies with the requirements of Regulation (EU) 2024/1689 (EU AI Act) for the indicated risk class.
126
+ 4. References to harmonised standards / specifications: _fill_
127
+ 5. Notified body (if applicable): _fill_
128
+ 6. Place, date, signature.
129
+
130
+ ---
131
+
132
+ _Attest scaffold — not a signed legal document._
133
+ `;
134
+ const p1 = path.join(out, 'technical-documentation.md');
135
+ const p2 = path.join(out, 'risk-assessment.md');
136
+ const p3 = path.join(out, 'conformity-declaration.md');
137
+ fs.writeFileSync(p1, technical, 'utf8');
138
+ fs.writeFileSync(p2, riskMd, 'utf8');
139
+ fs.writeFileSync(p3, decl, 'utf8');
140
+ files.push(p1, p2, p3);
141
+ return { files };
142
+ }
143
+ //# sourceMappingURL=docs-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs-generator.js","sourceRoot":"","sources":["../src/docs-generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export { AI_SDK_PACKAGES, HIGH_RISK_KEYWORDS, PROHIBITED_KEYWORDS } from './ai-packages.js';
2
+ export { Attest, defaultAuditPath } from './attest.js';
3
+ export { AuditLogger } from './audit-logger.js';
4
+ export type { AuditEntry } from './audit-logger.js';
5
+ export { checkCompliance } from './compliance-checker.js';
6
+ export { classifyRisk, riskLevelOrder } from './risk-classifier.js';
7
+ export { generateAnnexIvDocs } from './docs-generator.js';
8
+ export { scanProject } from './scanner.js';
9
+ export { getDisclosure } from './transparency.js';
10
+ export type { DisclosureLocale } from './transparency.js';
11
+ export type { AttestConfig, AttestEuConfig, AttestSystemConfig, ComplianceCheck, ComplianceReport, ComplianceStatus, ExportAuditOptions, GenerateDocsOptions, RiskClassification, RiskLevel, ScanFinding, ScanResult, TrackMeta, } from './types.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5F,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,YAAY,EACV,YAAY,EACZ,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,SAAS,EACT,WAAW,EACX,UAAU,EACV,SAAS,GACV,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ export { AI_SDK_PACKAGES, HIGH_RISK_KEYWORDS, PROHIBITED_KEYWORDS } from './ai-packages.js';
2
+ export { Attest, defaultAuditPath } from './attest.js';
3
+ export { AuditLogger } from './audit-logger.js';
4
+ export { checkCompliance } from './compliance-checker.js';
5
+ export { classifyRisk, riskLevelOrder } from './risk-classifier.js';
6
+ export { generateAnnexIvDocs } from './docs-generator.js';
7
+ export { scanProject } from './scanner.js';
8
+ export { getDisclosure } from './transparency.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5F,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { RiskClassification, RiskLevel, ScanResult } from './types.js';
2
+ export interface ClassifyContext {
3
+ /** Combined source text hint (optional; if omitted, reads from disk). */
4
+ corpus?: string;
5
+ }
6
+ export declare function classifyRisk(scan: ScanResult, context?: ClassifyContext): RiskClassification;
7
+ export declare function riskLevelOrder(level: RiskLevel): number;
8
+ //# sourceMappingURL=risk-classifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"risk-classifier.d.ts","sourceRoot":"","sources":["../src/risk-classifier.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAgC5E,MAAM,WAAW,eAAe;IAC9B,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,UAAU,EAChB,OAAO,CAAC,EAAE,eAAe,GACxB,kBAAkB,CAwDpB;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAQvD"}
@@ -0,0 +1,95 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { HIGH_RISK_KEYWORDS, PROHIBITED_KEYWORDS, } from './ai-packages.js';
4
+ function readAllSourceText(rootDir, maxBytes = 2_000_000) {
5
+ const parts = [];
6
+ let total = 0;
7
+ const walk = (dir) => {
8
+ let entries;
9
+ try {
10
+ entries = fs.readdirSync(dir, { withFileTypes: true });
11
+ }
12
+ catch {
13
+ return;
14
+ }
15
+ for (const e of entries) {
16
+ if (e.name === 'node_modules' || e.name === '.git' || e.name === 'dist')
17
+ continue;
18
+ const full = path.join(dir, e.name);
19
+ if (e.isDirectory())
20
+ walk(full);
21
+ else if (/\.(ts|tsx|js|jsx|md|json|env)$/i.test(e.name)) {
22
+ try {
23
+ const buf = fs.readFileSync(full);
24
+ if (total + buf.length > maxBytes)
25
+ return;
26
+ total += buf.length;
27
+ parts.push(buf.toString('utf8'));
28
+ }
29
+ catch {
30
+ /* ignore */
31
+ }
32
+ }
33
+ }
34
+ };
35
+ walk(rootDir);
36
+ return parts.join('\n').toLowerCase();
37
+ }
38
+ export function classifyRisk(scan, context) {
39
+ const warnings = [];
40
+ const articles = [];
41
+ const corpus = context?.corpus?.toLowerCase() ?? readAllSourceText(scan.rootDir);
42
+ for (const kw of PROHIBITED_KEYWORDS) {
43
+ if (corpus.includes(kw.toLowerCase())) {
44
+ return {
45
+ level: 'prohibited',
46
+ reason: `Possible prohibited practice indicated by keyword: "${kw}". Legal review required.`,
47
+ articles: ['Article 5'],
48
+ warnings: [
49
+ 'Heuristic scan only — not legal advice. Consult qualified counsel.',
50
+ ],
51
+ };
52
+ }
53
+ }
54
+ let highHit = false;
55
+ for (const kw of HIGH_RISK_KEYWORDS) {
56
+ if (corpus.includes(kw.toLowerCase())) {
57
+ highHit = true;
58
+ warnings.push(`High-risk context hint: "${kw}"`);
59
+ }
60
+ }
61
+ if (scan.packagesDetected.length === 0) {
62
+ return {
63
+ level: 'minimal',
64
+ reason: 'No known AI SDK imports detected in scanned files.',
65
+ articles: [],
66
+ warnings,
67
+ };
68
+ }
69
+ if (highHit) {
70
+ articles.push('Annex III', 'Articles 9–15', 'Article 26');
71
+ return {
72
+ level: 'high',
73
+ reason: 'AI SDK usage detected together with keywords suggesting Annex III high-risk domains (heuristic).',
74
+ articles,
75
+ warnings,
76
+ };
77
+ }
78
+ articles.push('Article 50');
79
+ return {
80
+ level: 'limited',
81
+ reason: 'AI SDK usage detected; likely transparency obligations for interactable AI (e.g. chatbots) under limited-risk rules.',
82
+ articles,
83
+ warnings,
84
+ };
85
+ }
86
+ export function riskLevelOrder(level) {
87
+ const o = {
88
+ minimal: 0,
89
+ limited: 1,
90
+ high: 2,
91
+ prohibited: 3,
92
+ };
93
+ return o[level];
94
+ }
95
+ //# sourceMappingURL=risk-classifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"risk-classifier.js","sourceRoot":"","sources":["../src/risk-classifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { ScanResult } from './types.js';
2
+ export interface ScanOptions {
3
+ rootDir: string;
4
+ }
5
+ export declare function scanProject(options: ScanOptions): ScanResult;
6
+ //# sourceMappingURL=scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAe,UAAU,EAAE,MAAM,YAAY,CAAC;AAwI1D,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,UAAU,CA8B5D"}
@@ -0,0 +1,151 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import * as ts from 'typescript';
4
+ import { AI_SDK_PACKAGES } from './ai-packages.js';
5
+ const SKIP_DIRS = new Set([
6
+ 'node_modules',
7
+ '.git',
8
+ 'dist',
9
+ 'build',
10
+ '.next',
11
+ 'coverage',
12
+ '.turbo',
13
+ 'vendor',
14
+ ]);
15
+ const EXT = new Set(['.ts', '.tsx', '.mts', '.cts', '.js', '.jsx', '.mjs', '.cjs']);
16
+ const AI_SET = new Set(AI_SDK_PACKAGES.map((p) => p.toLowerCase()));
17
+ function normalizeSpecifier(spec) {
18
+ const s = spec.trim();
19
+ if (!s || s.startsWith('.'))
20
+ return null;
21
+ const bare = s.startsWith('@')
22
+ ? s.split('/').slice(0, 2).join('/')
23
+ : s.split('/')[0] ?? s;
24
+ return bare?.toLowerCase() ?? null;
25
+ }
26
+ function matchesAiPackage(spec) {
27
+ const n = normalizeSpecifier(spec);
28
+ if (!n)
29
+ return null;
30
+ if (AI_SET.has(n))
31
+ return n;
32
+ for (const p of AI_SDK_PACKAGES) {
33
+ if (n === p.toLowerCase() || n.startsWith(`${p.toLowerCase()}/`))
34
+ return p;
35
+ }
36
+ return null;
37
+ }
38
+ function walkDir(dir, out) {
39
+ let entries;
40
+ try {
41
+ entries = fs.readdirSync(dir, { withFileTypes: true });
42
+ }
43
+ catch {
44
+ return;
45
+ }
46
+ for (const e of entries) {
47
+ if (e.name.startsWith('.'))
48
+ continue;
49
+ const full = path.join(dir, e.name);
50
+ if (e.isDirectory()) {
51
+ if (SKIP_DIRS.has(e.name))
52
+ continue;
53
+ walkDir(full, out);
54
+ }
55
+ else if (e.isFile()) {
56
+ const ext = path.extname(e.name);
57
+ if (EXT.has(ext))
58
+ out.push(full);
59
+ }
60
+ }
61
+ }
62
+ function getLine(source, pos) {
63
+ return source.slice(0, pos).split('\n').length;
64
+ }
65
+ function scriptKindForPath(absPath) {
66
+ const lower = absPath.toLowerCase();
67
+ if (lower.endsWith('.tsx'))
68
+ return ts.ScriptKind.TSX;
69
+ if (lower.endsWith('.jsx'))
70
+ return ts.ScriptKind.JSX;
71
+ if (lower.endsWith('.js') || lower.endsWith('.mjs') || lower.endsWith('.cjs'))
72
+ return ts.ScriptKind.JS;
73
+ return ts.ScriptKind.TS;
74
+ }
75
+ function visitSource(filePath, absPath, content, findings) {
76
+ const sf = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true, scriptKindForPath(absPath));
77
+ const visit = (node) => {
78
+ if (ts.isImportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
79
+ const spec = node.moduleSpecifier.text;
80
+ const pkg = matchesAiPackage(spec);
81
+ if (pkg) {
82
+ findings.push({
83
+ packageName: pkg,
84
+ filePath,
85
+ line: getLine(content, node.getStart(sf)),
86
+ kind: 'import',
87
+ });
88
+ }
89
+ }
90
+ if (ts.isCallExpression(node)) {
91
+ const expr = node.expression;
92
+ if (ts.isIdentifier(expr) && expr.text === 'require' && node.arguments.length > 0) {
93
+ const arg0 = node.arguments[0];
94
+ if (ts.isStringLiteral(arg0)) {
95
+ const pkg = matchesAiPackage(arg0.text);
96
+ if (pkg) {
97
+ findings.push({
98
+ packageName: pkg,
99
+ filePath,
100
+ line: getLine(content, node.getStart(sf)),
101
+ kind: 'require',
102
+ });
103
+ }
104
+ }
105
+ }
106
+ // dynamic import('pkg')
107
+ if (expr.kind === ts.SyntaxKind.ImportKeyword && node.arguments.length > 0) {
108
+ const arg0 = node.arguments[0];
109
+ if (ts.isStringLiteral(arg0)) {
110
+ const pkg = matchesAiPackage(arg0.text);
111
+ if (pkg) {
112
+ findings.push({
113
+ packageName: pkg,
114
+ filePath,
115
+ line: getLine(content, node.getStart(sf)),
116
+ kind: 'dynamic_import',
117
+ });
118
+ }
119
+ }
120
+ }
121
+ }
122
+ ts.forEachChild(node, visit);
123
+ };
124
+ visit(sf);
125
+ }
126
+ export function scanProject(options) {
127
+ const rootDir = path.resolve(options.rootDir);
128
+ const files = [];
129
+ walkDir(rootDir, files);
130
+ const findings = [];
131
+ let scanned = 0;
132
+ for (const file of files) {
133
+ let content;
134
+ try {
135
+ content = fs.readFileSync(file, 'utf8');
136
+ }
137
+ catch {
138
+ continue;
139
+ }
140
+ scanned += 1;
141
+ visitSource(path.relative(rootDir, file).replace(/\\/g, '/'), file, content, findings);
142
+ }
143
+ const packagesDetected = [...new Set(findings.map((f) => f.packageName))].sort();
144
+ return {
145
+ rootDir,
146
+ filesScanned: scanned,
147
+ findings,
148
+ packagesDetected,
149
+ };
150
+ }
151
+ //# sourceMappingURL=scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=scanner.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.test.d.ts","sourceRoot":"","sources":["../src/scanner.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,21 @@
1
+ import * as fs from 'node:fs';
2
+ import * as os from 'node:os';
3
+ import * as path from 'node:path';
4
+ import { describe, expect, it } from 'vitest';
5
+ import { scanProject } from './scanner.js';
6
+ describe('scanProject', () => {
7
+ it('detects openai import', () => {
8
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'attest-scan-'));
9
+ fs.writeFileSync(path.join(dir, 'app.ts'), `import OpenAI from 'openai';\nconst x = new OpenAI();\n`, 'utf8');
10
+ const r = scanProject({ rootDir: dir });
11
+ expect(r.packagesDetected).toContain('openai');
12
+ expect(r.findings.some((f) => f.packageName === 'openai')).toBe(true);
13
+ });
14
+ it('detects require anthropic', () => {
15
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'attest-scan-'));
16
+ fs.writeFileSync(path.join(dir, 'legacy.js'), `const Anthropic = require("@anthropic-ai/sdk");\n`, 'utf8');
17
+ const r = scanProject({ rootDir: dir });
18
+ expect(r.packagesDetected).toContain('@anthropic-ai/sdk');
19
+ });
20
+ });
21
+ //# sourceMappingURL=scanner.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.test.js","sourceRoot":"","sources":["../src/scanner.test.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,MAAM,GAAG,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC;QACnE,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,EACxB,yDAAyD,EACzD,MAAM,CACP,CAAC;QACF,MAAM,CAAC,GAAG,WAAW,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;QACxC,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC/C,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACnC,MAAM,GAAG,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC;QACnE,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,EAC3B,mDAAmD,EACnD,MAAM,CACP,CAAC;QACF,MAAM,CAAC,GAAG,WAAW,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;QACxC,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ export type DisclosureLocale = 'en' | 'fi' | 'de' | 'fr' | 'es' | 'nl' | 'it' | 'pt';
2
+ export declare function getDisclosure(locale?: DisclosureLocale, options?: {
3
+ humanAvailable?: boolean;
4
+ }): string;
5
+ //# sourceMappingURL=transparency.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transparency.d.ts","sourceRoot":"","sources":["../src/transparency.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GACxB,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,CAAC;AAgDT,wBAAgB,aAAa,CAC3B,MAAM,GAAE,gBAAuB,EAC/B,OAAO,CAAC,EAAE;IAAE,cAAc,CAAC,EAAE,OAAO,CAAA;CAAE,GACrC,MAAM,CAGR"}
@@ -0,0 +1,39 @@
1
+ const MESSAGES = {
2
+ en: {
3
+ short: 'This experience may be powered by artificial intelligence.',
4
+ withHuman: 'This conversation is powered by artificial intelligence. A human operator is available upon request.',
5
+ },
6
+ fi: {
7
+ short: 'Tama kokemus voi perustua tekoalyyn.',
8
+ withHuman: 'Tama keskustelu kayttaa tekoalya. Ihminen on saatavilla pyynnosta.',
9
+ },
10
+ de: {
11
+ short: 'Dieses Erlebnis kann KI-gestutzt sein.',
12
+ withHuman: 'Dieses Gesprach wird durch kunstliche Intelligenz unterstutzt. Ein menschlicher Ansprechpartner ist auf Anfrage verfugbar.',
13
+ },
14
+ fr: {
15
+ short: 'Cette experience peut etre assistee par une intelligence artificielle.',
16
+ withHuman: 'Cette conversation est assistee par une intelligence artificielle. Un operateur humain est disponible sur demande.',
17
+ },
18
+ es: {
19
+ short: 'Esta experiencia puede estar asistida por inteligencia artificial.',
20
+ withHuman: 'Esta conversacion esta asistida por inteligencia artificial. Un operador humano esta disponible bajo solicitud.',
21
+ },
22
+ nl: {
23
+ short: 'Deze ervaring kan met kunstmatige intelligentie worden ondersteund.',
24
+ withHuman: 'Dit gesprek wordt ondersteund door kunstmatige intelligentie. Een menselijke medewerker is op verzoek beschikbaar.',
25
+ },
26
+ it: {
27
+ short: 'Questa esperienza puo essere supportata da intelligenza artificiale.',
28
+ withHuman: 'Questa conversazione e supportata da intelligenza artificiale. Un operatore umano e disponibile su richiesta.',
29
+ },
30
+ pt: {
31
+ short: 'Esta experiencia pode ser apoiada por inteligencia artificial.',
32
+ withHuman: 'Esta conversa e apoiada por inteligencia artificial. Um operador humano esta disponivel mediante pedido.',
33
+ },
34
+ };
35
+ export function getDisclosure(locale = 'en', options) {
36
+ const pack = MESSAGES[locale] ?? MESSAGES.en;
37
+ return options?.humanAvailable ? pack.withHuman : pack.short;
38
+ }
39
+ //# sourceMappingURL=transparency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transparency.js","sourceRoot":"","sources":["../src/transparency.ts"],"names":[],"mappings":"AAUA,MAAM,QAAQ,GAGV;IACF,EAAE,EAAE;QACF,KAAK,EAAE,4DAA4D;QACnE,SAAS,EACP,sGAAsG;KACzG;IACD,EAAE,EAAE;QACF,KAAK,EAAE,sCAAsC;QAC7C,SAAS,EACP,oEAAoE;KACvE;IACD,EAAE,EAAE;QACF,KAAK,EAAE,wCAAwC;QAC/C,SAAS,EACP,4HAA4H;KAC/H;IACD,EAAE,EAAE;QACF,KAAK,EAAE,wEAAwE;QAC/E,SAAS,EACP,oHAAoH;KACvH;IACD,EAAE,EAAE;QACF,KAAK,EAAE,oEAAoE;QAC3E,SAAS,EACP,iHAAiH;KACpH;IACD,EAAE,EAAE;QACF,KAAK,EAAE,qEAAqE;QAC5E,SAAS,EACP,oHAAoH;KACvH;IACD,EAAE,EAAE;QACF,KAAK,EAAE,sEAAsE;QAC7E,SAAS,EACP,+GAA+G;KAClH;IACD,EAAE,EAAE;QACF,KAAK,EAAE,gEAAgE;QACvE,SAAS,EACP,0GAA0G;KAC7G;CACF,CAAC;AAEF,MAAM,UAAU,aAAa,CAC3B,SAA2B,IAAI,EAC/B,OAAsC;IAEtC,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,QAAQ,CAAC,EAAE,CAAC;IAC7C,OAAO,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;AAC/D,CAAC"}
@@ -0,0 +1,63 @@
1
+ export type RiskLevel = 'minimal' | 'limited' | 'high' | 'prohibited';
2
+ export interface ScanFinding {
3
+ readonly packageName: string;
4
+ readonly filePath: string;
5
+ readonly line: number;
6
+ readonly kind: 'import' | 'require' | 'dynamic_import';
7
+ }
8
+ export interface ScanResult {
9
+ readonly rootDir: string;
10
+ readonly filesScanned: number;
11
+ readonly findings: ScanFinding[];
12
+ readonly packagesDetected: string[];
13
+ }
14
+ export interface RiskClassification {
15
+ readonly level: RiskLevel;
16
+ readonly reason: string;
17
+ readonly articles: string[];
18
+ readonly warnings: string[];
19
+ }
20
+ export type ComplianceStatus = 'pass' | 'fail' | 'warn';
21
+ export interface ComplianceCheck {
22
+ readonly id: string;
23
+ readonly label: string;
24
+ readonly status: ComplianceStatus;
25
+ readonly detail: string;
26
+ }
27
+ export interface ComplianceReport {
28
+ readonly checks: ComplianceCheck[];
29
+ readonly score: number;
30
+ }
31
+ export interface AttestSystemConfig {
32
+ name: string;
33
+ provider: string;
34
+ description?: string;
35
+ }
36
+ export interface AttestEuConfig {
37
+ deployerCountry?: string;
38
+ registrationId?: string;
39
+ }
40
+ export interface AttestConfig {
41
+ system: AttestSystemConfig;
42
+ eu?: AttestEuConfig;
43
+ /** Optional path to project root for scans (default: cwd). */
44
+ projectRoot?: string;
45
+ /** Audit log file path (JSONL). */
46
+ auditLogPath?: string;
47
+ }
48
+ export interface TrackMeta {
49
+ purpose?: string;
50
+ humanOversight?: 'available' | 'required' | 'none';
51
+ containsPII?: boolean;
52
+ model?: string;
53
+ }
54
+ export interface GenerateDocsOptions {
55
+ outputDir: string;
56
+ format?: 'markdown';
57
+ language?: string;
58
+ }
59
+ export interface ExportAuditOptions {
60
+ format: 'json' | 'jsonl';
61
+ from?: string;
62
+ }
63
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,YAAY,CAAC;AAEtE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,gBAAgB,CAAC;CACxD;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,WAAW,EAAE,CAAC;IACjC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAExD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,EAAE,CAAC,EAAE,cAAc,CAAC;IACpB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mCAAmC;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,WAAW,GAAG,UAAU,GAAG,MAAM,CAAC;IACnD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@asterpay/attest-sdk",
3
+ "version": "0.1.0",
4
+ "description": "EU AI Act compliance toolkit for TypeScript — scanner, risk classification, docs, audit logging.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "README.md"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "typecheck": "tsc --noEmit",
21
+ "test": "vitest run"
22
+ },
23
+ "keywords": [
24
+ "eu-ai-act",
25
+ "compliance",
26
+ "ai",
27
+ "gdpr",
28
+ "audit",
29
+ "typescript"
30
+ ],
31
+ "license": "MIT",
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "https://github.com/AsterPay/attest"
35
+ },
36
+ "homepage": "https://github.com/AsterPay/attest",
37
+ "dependencies": {
38
+ "typescript": "^5.7.3"
39
+ },
40
+ "devDependencies": {
41
+ "@types/node": "^20.11.16",
42
+ "vitest": "^3.0.5"
43
+ },
44
+ "engines": {
45
+ "node": ">=18.0.0"
46
+ }
47
+ }