npl-presence-cli 1.0.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/README.md +55 -0
- package/dist/commands/id.d.ts +6 -0
- package/dist/commands/id.js +47 -0
- package/dist/commands/keypair.d.ts +6 -0
- package/dist/commands/keypair.js +34 -0
- package/dist/commands/presence.d.ts +6 -0
- package/dist/commands/presence.js +51 -0
- package/dist/commands/rr.d.ts +6 -0
- package/dist/commands/rr.js +65 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +23 -0
- package/package.json +44 -0
package/README.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# @nextera.one/npl-cli
|
|
2
|
+
|
|
3
|
+
Command-line interface for **NPL (Network Presence Layer)** operations.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @nextera.one/npl-cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Commands
|
|
12
|
+
|
|
13
|
+
### Presence Objects
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Create a presence object
|
|
17
|
+
npl presence create -s "device:sensor-001" --scopes net,log --ttl 5
|
|
18
|
+
|
|
19
|
+
# Validate a presence object
|
|
20
|
+
npl presence validate '{"ver":1,"alg":"ed25519","pay":{...}}'
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### NPL-ID
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Generate presence and compute NPL-ID
|
|
27
|
+
npl id generate -s "user:alice" --scopes net,auth
|
|
28
|
+
|
|
29
|
+
# Compute NPL-ID from existing presence
|
|
30
|
+
npl id compute '{"ver":1,"alg":"ed25519","pay":{...}}'
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Resolution Records
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Create a resolution record
|
|
37
|
+
npl rr create --npl-id <hash> --ip 192.168.1.1 --ip 10.0.0.1 --ttl 5
|
|
38
|
+
|
|
39
|
+
# Validate a resolution record
|
|
40
|
+
npl rr validate '{"ver":1,"typ":"NPL-RR",...}'
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Keypairs
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Generate Ed25519 keypair
|
|
47
|
+
npl keypair generate
|
|
48
|
+
|
|
49
|
+
# Generate with base64 format
|
|
50
|
+
npl keypair generate --format base64
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## License
|
|
54
|
+
|
|
55
|
+
Apache-2.0
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NPL CLI - ID Command
|
|
3
|
+
* Compute and display NPL-IDs
|
|
4
|
+
*/
|
|
5
|
+
import { Command } from 'commander';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import { createPresence, computeNplId } from '@nextera.one/npl-sdk';
|
|
8
|
+
export const idCommand = new Command('id')
|
|
9
|
+
.description('NPL-ID operations');
|
|
10
|
+
idCommand
|
|
11
|
+
.command('compute')
|
|
12
|
+
.description('Compute NPL-ID from a presence object')
|
|
13
|
+
.argument('<json>', 'Presence object JSON')
|
|
14
|
+
.action((json) => {
|
|
15
|
+
try {
|
|
16
|
+
const presence = JSON.parse(json);
|
|
17
|
+
const nplId = computeNplId(presence);
|
|
18
|
+
console.log(chalk.green('NPL-ID:'));
|
|
19
|
+
console.log(chalk.cyan(nplId));
|
|
20
|
+
console.log();
|
|
21
|
+
console.log(chalk.dim('Short:'), nplId.substring(0, 16) + '...');
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
console.error(chalk.red('Error:'), err);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
idCommand
|
|
29
|
+
.command('generate')
|
|
30
|
+
.description('Create a presence and compute its NPL-ID')
|
|
31
|
+
.requiredOption('-s, --subject <subject>', 'Subject identity')
|
|
32
|
+
.option('--scopes <scopes>', 'Comma-separated scopes', 'net')
|
|
33
|
+
.option('--ttl <minutes>', 'TTL in minutes', '5')
|
|
34
|
+
.action((options) => {
|
|
35
|
+
const scopes = options.scopes.split(',');
|
|
36
|
+
const ttl = parseInt(options.ttl, 10);
|
|
37
|
+
const presence = createPresence(options.subject, scopes, ttl);
|
|
38
|
+
const nplId = computeNplId(presence);
|
|
39
|
+
console.log(chalk.green('✓ NPL-ID generated'));
|
|
40
|
+
console.log();
|
|
41
|
+
console.log(chalk.dim('Subject:'), options.subject);
|
|
42
|
+
console.log(chalk.dim('Scopes:'), scopes.join(', '));
|
|
43
|
+
console.log(chalk.dim('TTL:'), `${ttl} minutes`);
|
|
44
|
+
console.log();
|
|
45
|
+
console.log(chalk.green('NPL-ID:'));
|
|
46
|
+
console.log(chalk.cyan(nplId));
|
|
47
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NPL CLI - Keypair Command
|
|
3
|
+
* Generate and manage Ed25519 keypairs
|
|
4
|
+
*/
|
|
5
|
+
import { Command } from 'commander';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import { generateKeypair, bytesToHex } from '@nextera.one/npl-sdk';
|
|
8
|
+
export const keypairCommand = new Command('keypair')
|
|
9
|
+
.description('Keypair operations');
|
|
10
|
+
keypairCommand
|
|
11
|
+
.command('generate')
|
|
12
|
+
.description('Generate a new Ed25519 keypair')
|
|
13
|
+
.option('--format <format>', 'Output format (hex, base64)', 'hex')
|
|
14
|
+
.action(async (options) => {
|
|
15
|
+
const keypair = await generateKeypair();
|
|
16
|
+
console.log(chalk.green('✓ Ed25519 keypair generated'));
|
|
17
|
+
console.log();
|
|
18
|
+
if (options.format === 'hex') {
|
|
19
|
+
console.log(chalk.dim('Private Key (hex):'));
|
|
20
|
+
console.log(chalk.yellow(bytesToHex(keypair.privateKey)));
|
|
21
|
+
console.log();
|
|
22
|
+
console.log(chalk.dim('Public Key (hex):'));
|
|
23
|
+
console.log(chalk.cyan(bytesToHex(keypair.publicKey)));
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
console.log(chalk.dim('Private Key (base64):'));
|
|
27
|
+
console.log(chalk.yellow(Buffer.from(keypair.privateKey).toString('base64')));
|
|
28
|
+
console.log();
|
|
29
|
+
console.log(chalk.dim('Public Key (base64):'));
|
|
30
|
+
console.log(chalk.cyan(Buffer.from(keypair.publicKey).toString('base64')));
|
|
31
|
+
}
|
|
32
|
+
console.log();
|
|
33
|
+
console.log(chalk.red('⚠ Store the private key securely!'));
|
|
34
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NPL CLI - Presence Command
|
|
3
|
+
* Create and validate presence objects
|
|
4
|
+
*/
|
|
5
|
+
import { Command } from 'commander';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import { createPresence, validatePresence, formatPresence, isPresenceValid, getPresenceTtl, } from '@nextera.one/npl-sdk';
|
|
8
|
+
export const presenceCommand = new Command('presence')
|
|
9
|
+
.description('Presence object operations');
|
|
10
|
+
presenceCommand
|
|
11
|
+
.command('create')
|
|
12
|
+
.description('Create a new NPL presence object')
|
|
13
|
+
.requiredOption('-s, --subject <subject>', 'Subject identity')
|
|
14
|
+
.option('--scopes <scopes>', 'Comma-separated scopes (net,log,auth,exec)', 'net')
|
|
15
|
+
.option('--ttl <minutes>', 'TTL in minutes', '5')
|
|
16
|
+
.option('--anchor <type>', 'Trust anchor type (geo,carrier,org,dns,hardware,jur)')
|
|
17
|
+
.action((options) => {
|
|
18
|
+
const scopes = options.scopes.split(',');
|
|
19
|
+
const ttl = parseInt(options.ttl, 10);
|
|
20
|
+
const presence = createPresence(options.subject, scopes, ttl, options.anchor);
|
|
21
|
+
console.log(chalk.green('✓ Presence object created'));
|
|
22
|
+
console.log();
|
|
23
|
+
console.log(formatPresence(presence));
|
|
24
|
+
});
|
|
25
|
+
presenceCommand
|
|
26
|
+
.command('validate')
|
|
27
|
+
.description('Validate a presence object from JSON')
|
|
28
|
+
.argument('<json>', 'Presence object JSON')
|
|
29
|
+
.action((json) => {
|
|
30
|
+
try {
|
|
31
|
+
const presence = JSON.parse(json);
|
|
32
|
+
const result = validatePresence(presence);
|
|
33
|
+
if (result.ok) {
|
|
34
|
+
console.log(chalk.green('✓ Presence object is valid'));
|
|
35
|
+
console.log();
|
|
36
|
+
console.log('Status:', isPresenceValid(presence) ? chalk.green('Active') : chalk.red('Expired'));
|
|
37
|
+
console.log('TTL:', chalk.cyan(`${getPresenceTtl(presence)}s remaining`));
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
console.log(chalk.red('✗ Presence object is invalid'));
|
|
41
|
+
result.errors.forEach((err) => {
|
|
42
|
+
console.log(chalk.red(` - ${err}`));
|
|
43
|
+
});
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
console.error(chalk.red('Error parsing JSON:'), err);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NPL CLI - Resolution Record Command
|
|
3
|
+
* Create and validate resolution records
|
|
4
|
+
*/
|
|
5
|
+
import { Command } from 'commander';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import { createResolutionRecord, validateResolutionRecord, isResolutionRecordValid, } from '@nextera.one/npl-sdk';
|
|
8
|
+
export const rrCommand = new Command('rr')
|
|
9
|
+
.description('Resolution record operations');
|
|
10
|
+
rrCommand
|
|
11
|
+
.command('create')
|
|
12
|
+
.description('Create a resolution record')
|
|
13
|
+
.requiredOption('--npl-id <id>', 'NPL-ID to bind')
|
|
14
|
+
.requiredOption('--ip <ip>', 'IP address (can be specified multiple times)', collect, [])
|
|
15
|
+
.option('--ttl <minutes>', 'TTL in minutes', '5')
|
|
16
|
+
.option('--ports <ports>', 'Comma-separated port numbers')
|
|
17
|
+
.option('--proto <protocols>', 'Comma-separated protocols (tcp,quic,udp)')
|
|
18
|
+
.action((options) => {
|
|
19
|
+
const ips = options.ip.map((ip) => ({
|
|
20
|
+
ip,
|
|
21
|
+
fam: ip.includes(':') ? 6 : 4,
|
|
22
|
+
}));
|
|
23
|
+
const ctx = {};
|
|
24
|
+
if (options.ports) {
|
|
25
|
+
ctx.port = options.ports.split(',').map((p) => parseInt(p, 10));
|
|
26
|
+
}
|
|
27
|
+
if (options.proto) {
|
|
28
|
+
ctx.proto = options.proto.split(',');
|
|
29
|
+
}
|
|
30
|
+
const rr = createResolutionRecord(options.nplId, ips, parseInt(options.ttl, 10), Object.keys(ctx).length > 0 ? ctx : undefined);
|
|
31
|
+
console.log(chalk.green('✓ Resolution record created'));
|
|
32
|
+
console.log();
|
|
33
|
+
console.log(JSON.stringify(rr, null, 2));
|
|
34
|
+
});
|
|
35
|
+
rrCommand
|
|
36
|
+
.command('validate')
|
|
37
|
+
.description('Validate a resolution record')
|
|
38
|
+
.argument('<json>', 'Resolution record JSON')
|
|
39
|
+
.action((json) => {
|
|
40
|
+
try {
|
|
41
|
+
const rr = JSON.parse(json);
|
|
42
|
+
const result = validateResolutionRecord(rr);
|
|
43
|
+
if (result.ok) {
|
|
44
|
+
console.log(chalk.green('✓ Resolution record is valid'));
|
|
45
|
+
console.log();
|
|
46
|
+
console.log('Status:', isResolutionRecordValid(rr) ? chalk.green('Active') : chalk.red('Expired'));
|
|
47
|
+
console.log('NPL-ID:', chalk.cyan(rr.npl_id.substring(0, 16) + '...'));
|
|
48
|
+
console.log('IPs:', rr.ips.map((ip) => ip.ip).join(', '));
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
console.log(chalk.red('✗ Resolution record is invalid'));
|
|
52
|
+
result.errors.forEach((err) => {
|
|
53
|
+
console.log(chalk.red(` - ${err}`));
|
|
54
|
+
});
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
console.error(chalk.red('Error parsing JSON:'), err);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
function collect(value, previous) {
|
|
64
|
+
return previous.concat([value]);
|
|
65
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* NPL CLI - Network Presence Layer
|
|
4
|
+
* Command-line interface for NPL operations
|
|
5
|
+
*/
|
|
6
|
+
import { Command } from 'commander';
|
|
7
|
+
import { presenceCommand } from './commands/presence.js';
|
|
8
|
+
import { idCommand } from './commands/id.js';
|
|
9
|
+
import { rrCommand } from './commands/rr.js';
|
|
10
|
+
import { keypairCommand } from './commands/keypair.js';
|
|
11
|
+
const program = new Command();
|
|
12
|
+
program
|
|
13
|
+
.name('npl')
|
|
14
|
+
.description('NPL CLI - Network Presence Layer operations')
|
|
15
|
+
.version('1.0.0');
|
|
16
|
+
program.addCommand(presenceCommand);
|
|
17
|
+
program.addCommand(idCommand);
|
|
18
|
+
program.addCommand(rrCommand);
|
|
19
|
+
program.addCommand(keypairCommand);
|
|
20
|
+
program.parse(process.argv);
|
|
21
|
+
if (!process.argv.slice(2).length) {
|
|
22
|
+
program.outputHelp();
|
|
23
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "npl-presence-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "NPL CLI - Network Presence Layer command-line interface",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"npl": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"README.md"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"start": "node dist/index.js",
|
|
16
|
+
"test": "npm run build && node --test",
|
|
17
|
+
"prepare": "npm run build"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"npl",
|
|
21
|
+
"network-presence",
|
|
22
|
+
"cli",
|
|
23
|
+
"cryptographic",
|
|
24
|
+
"verification",
|
|
25
|
+
"nextera",
|
|
26
|
+
"presence-layer"
|
|
27
|
+
],
|
|
28
|
+
"author": "NextEra.One",
|
|
29
|
+
"license": "Apache-2.0",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "https://github.com/nextera-one/npl"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://npl-standard.org",
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"chalk": "^5.6.2",
|
|
37
|
+
"commander": "^14.0.2",
|
|
38
|
+
"npl-presence-sdk": "^1.0.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/node": "^25.0.3",
|
|
42
|
+
"typescript": "^5.9.3"
|
|
43
|
+
}
|
|
44
|
+
}
|