Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,34 @@ playwright-report/
# Variables
.env
.env.**

# Claude Flow generated files
.claude/settings.local.json
.mcp.json
claude-flow.config.json
.swarm/
.hive-mind/
.claude-flow/
memory/
coordination/
memory/claude-flow-data.json
memory/sessions/*
!memory/sessions/README.md
memory/agents/*
!memory/agents/README.md
coordination/memory_bank/*
coordination/subtasks/*
coordination/orchestration/*
*.db
*.db-journal
*.db-wal
*.sqlite
*.sqlite-journal
*.sqlite-wal
claude-flow
# Removed Windows wrapper files per user request
hive-mind-prompt-*.txt
.claude
.claude-flow
.hive-mind
packages/scaffold
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
auto-install-peers = true
1 change: 1 addition & 0 deletions packages/crypto/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# scaffold
Empty file added packages/crypto/docs/.gitkeep
Empty file.
149 changes: 149 additions & 0 deletions packages/crypto/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import js from '@eslint/js';
import tsPlugin from '@typescript-eslint/eslint-plugin';
import tsParser from '@typescript-eslint/parser';

export default [
js.configs.recommended,
{
files: ['src/**/*.ts'],
languageOptions: {
parser: tsParser,
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
project: './tsconfig.json',
},
},
plugins: {
'@typescript-eslint': tsPlugin,
},
rules: {
// Use strict TypeScript rules for maximum type safety
...tsPlugin.configs['recommended-type-checked'].rules,
...tsPlugin.configs['stylistic-type-checked'].rules,

// Type safety errors
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-unsafe-assignment': 'error',
'@typescript-eslint/no-unsafe-call': 'error',
'@typescript-eslint/no-unsafe-member-access': 'error',
'@typescript-eslint/no-unsafe-return': 'error',
'@typescript-eslint/no-unsafe-argument': 'error',
'@typescript-eslint/strict-boolean-expressions': ['error', {
allowString: false,
allowNumber: false,
allowNullableObject: false,
}],
'@typescript-eslint/no-floating-promises': 'error',
'@typescript-eslint/no-misused-promises': 'error',
'@typescript-eslint/await-thenable': 'error',
'@typescript-eslint/require-await': 'error',
'@typescript-eslint/no-unnecessary-type-assertion': 'error',
'@typescript-eslint/no-non-null-assertion': 'error',

// Code quality
'@typescript-eslint/no-unused-vars': ['error', {
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_',
}],
'@typescript-eslint/consistent-type-imports': ['error', {
prefer: 'type-imports',
fixStyle: 'inline-type-imports',
}],
'@typescript-eslint/consistent-type-exports': ['error', {
fixMixedExportsWithInlineTypeSpecifier: true,
}],
'@typescript-eslint/explicit-function-return-type': ['error', {
allowExpressions: true,
allowTypedFunctionExpressions: true,
allowHigherOrderFunctions: true,
}],
'@typescript-eslint/explicit-module-boundary-types': 'error',
'@typescript-eslint/no-redundant-type-constituents': 'error',

// Cross-environment compatibility
'no-restricted-globals': ['error',
// Node.js specific - disallow in cross-env code
{ name: 'process', message: 'Use platform detection instead' },
{ name: 'Buffer', message: 'Use Uint8Array for cross-platform compatibility' },
{ name: '__dirname', message: 'Not available in all environments' },
{ name: '__filename', message: 'Not available in all environments' },
// Browser-specific - disallow in cross-env code
{ name: 'window', message: 'Not available in Node.js/Bun' },
{ name: 'document', message: 'Not available in Node.js/Bun' },
{ name: 'navigator', message: 'Not available in Node.js/Bun' },
],
'no-restricted-syntax': ['error',
{
selector: 'NewExpression[callee.name="Buffer"]',
message: 'Use Uint8Array instead of Buffer for cross-platform compatibility',
},
],

// Best practices for library code
'no-console': 'error',
'no-var': 'error',
'prefer-const': 'error',
'prefer-arrow-callback': 'error',
'prefer-template': 'error',
'no-throw-literal': 'error',
'@typescript-eslint/prefer-nullish-coalescing': 'error',
'@typescript-eslint/prefer-optional-chain': 'error',
'@typescript-eslint/prefer-readonly': 'error',
'@typescript-eslint/prefer-reduce-type-parameter': 'error',
'@typescript-eslint/switch-exhaustiveness-check': 'error',
'@typescript-eslint/no-namespace': 'off',
},
},
{
files: ['tests/**/*.ts'],
languageOptions: {
parser: tsParser,
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
project: './tsconfig.json',
},
globals: {
describe: 'readonly',
test: 'readonly',
expect: 'readonly',
beforeEach: 'readonly',
afterEach: 'readonly',
beforeAll: 'readonly',
afterAll: 'readonly',
jest: 'readonly',
console: 'readonly',
Buffer: 'readonly',
},
},
plugins: {
'@typescript-eslint': tsPlugin,
},
rules: {
...tsPlugin.configs.recommended.rules,
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-unused-vars': ['warn', {
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
}],
'@typescript-eslint/no-non-null-assertion': 'warn',
'no-console': 'off',
'prefer-const': 'warn',
'no-var': 'error',
},
},
{
ignores: [
'dist/**',
'node_modules/**',
'coverage/**',
'**/*.js',
'scripts/**',
'examples/**',
],
},
];
26 changes: 26 additions & 0 deletions packages/crypto/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { Config } from 'jest';

const config: Config = {
preset: 'ts-jest',
testEnvironment: 'node',
roots: ['<rootDir>/tests'],
testMatch: ['**/*.test.ts'],
collectCoverageFrom: [
'src/**/*.ts',
'!src/**/*.d.ts',
'!src/**/index.ts',
],
coverageThreshold: {
global: {
branches: 90,
functions: 95,
lines: 95,
statements: 95,
},
},
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
},
};

export default config;
71 changes: 71 additions & 0 deletions packages/crypto/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{
"name": "@blockchain-commons/crypto",
"version": "1.0.0-alpha.1",
"type": "module",
"description": "A TypeScript implementation of Blockchain Commons cryptographic components. Supports key generation, signing, verification, encryption, and post-quantum cryptography.",
"main": "dist/index.cjs",
"module": "dist/index.mjs",
"types": "dist/index.d.mts",
"exports": {
".": {
"types": "./dist/index.d.mts",
"import": "./dist/index.mjs",
"require": "./dist/index.cjs",
"default": "./dist/index.mjs"
}
},
"files": [
"dist",
"README.md",
"LICENSE"
],
"scripts": {
"build": "tsdown",
"dev": "tsdown --watch",
"test": "jest",
"test:watch": "jest --watch",
"lint": "eslint 'src/**/*.ts' 'tests/**/*.ts'",
"lint:fix": "eslint 'src/**/*.ts' 'tests/**/*.ts' --fix",
"typecheck": "tsc --noEmit",
"clean": "rm -rf dist"
},
"keywords": [
"blockchain",
"commons",
"cryptography",
"keys",
"signatures",
"encryption",
"ed25519",
"secp256k1",
"post-quantum"
],
"engines": {
"node": ">=18.0.0"
},
"author": "Blockchain Commons",
"license": "Apache-2.0",
"dependencies": {
"@blockchain-commons/dcbor": "workspace:*",
"@blockchain-commons/uniform-resources": "workspace:*",
"@noble/curves": "^1.8.0",
"@noble/hashes": "^1.7.0",
"libsodium-wrappers": "^0.7.15",
"pako": "^2.1.0",
"tweetnacl": "^1.6.1"
},
"devDependencies": {
"@eslint/js": "^9.39.1",
"@jest/globals": "^30.0.0-beta.6",
"@types/jest": "^30.0.0-beta.2",
"@types/node": "^20.16.11",
"@types/pako": "^2.0.3",
"@typescript-eslint/eslint-plugin": "^8.47.0",
"@typescript-eslint/parser": "^8.47.0",
"eslint": "^9.39.1",
"jest": "^30.0.0-beta.6",
"prettier": "^3.2.5",
"ts-jest": "^29.4.5",
"typescript": "^5.9.3"
}
}
94 changes: 94 additions & 0 deletions packages/crypto/src/arid.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/**
* Apparently Random Identifier (ARID) - 32-byte random identifier
*/

import { CryptoError } from './error.js';

const ARID_SIZE = 32;

export class ARID {
private data: Uint8Array;

private constructor(data: Uint8Array) {
if (data.length !== ARID_SIZE) {
throw CryptoError.invalidSize(ARID_SIZE, data.length);
}
this.data = new Uint8Array(data);
}

/**
* Create an ARID from raw bytes
*/
static from(data: Uint8Array): ARID {
return new ARID(new Uint8Array(data));
}

/**
* Create an ARID from hex string
*/
static fromHex(hex: string): ARID {
const data = new Uint8Array(hex.length / 2);
for (let i = 0; i < hex.length; i += 2) {
data[i / 2] = parseInt(hex.substr(i, 2), 16);
}
return new ARID(data);
}

/**
* Generate a random ARID
*/
static random(): ARID {
const data = new Uint8Array(ARID_SIZE);
if (typeof globalThis !== 'undefined' && globalThis.crypto?.getRandomValues) {
globalThis.crypto.getRandomValues(data);
} else {
// Fallback for Node.js
const { randomBytes } = require('crypto');
const buf = randomBytes(ARID_SIZE);
data.set(buf);
}
return new ARID(data);
}

/**
* Get the raw ARID bytes
*/
toData(): Uint8Array {
return new Uint8Array(this.data);
}

/**
* Get hex string representation
*/
toHex(): string {
return Array.from(this.data)
.map(b => b.toString(16).padStart(2, '0'))
.join('')
.toUpperCase();
}

/**
* Get base64 representation
*/
toBase64(): string {
return Buffer.from(this.data).toString('base64');
}

/**
* Compare with another ARID
*/
equals(other: ARID): boolean {
if (this.data.length !== other.data.length) return false;
for (let i = 0; i < this.data.length; i++) {
if (this.data[i] !== other.data[i]) return false;
}
return true;
}

/**
* Get string representation
*/
toString(): string {
return `ARID(${this.toHex()})`;
}
}
Loading
Loading