nsecbunkerd/src/daemon/admin/commands/validate_token.ts
tcheeric 16dc15b486 feat!: Add Admin API methods and NIP-46 compliance
BREAKING CHANGE: Admin API now uses kind 24133 instead of 24134

This release adds 11 new admin methods and ensures full NIP-46 compliance
by switching from the non-standard kind 24134 to the spec-compliant 24133.

## New Admin Methods

### Key Management
- `get_key` - Get details about a specific key
- `delete_key` - Soft-delete a key and its tokens
- `rotate_key` - Create new key and migrate permissions

### Policy Management
- `get_policy` - Get policy details with rules
- `delete_policy` - Soft-delete a policy

### Permission Management
- `grant_permission` - Grant user access with a policy
- `revoke_permission` - Revoke user's access to a key
- `get_permissions` - Get user's permissions on a key

### Token Management
- `get_token` - Get token details
- `revoke_token` - Soft-delete a token
- `validate_token` - Check if a token is valid

## NIP-46 Compliance

Changed all admin communication from kind 24134 to kind 24133
(NDKKind.NostrConnect) to comply with the NIP-46 specification.
Kind 24134 was never part of the official spec.

## Other Changes

- Added Vitest test framework with 93 tests
- Fixed TypeScript compilation errors
- Updated documentation with breaking change notice
- Version bump to 0.11.0

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 03:41:15 +00:00

57 lines
1.8 KiB
TypeScript

import { NDKKind, NDKRpcRequest } from "@nostr-dev-kit/ndk";
import AdminInterface from "../index.js";
import prisma from "../../../db.js";
export default async function validateToken(admin: AdminInterface, req: NDKRpcRequest) {
const [tokenString] = req.params as [string];
if (!tokenString) throw new Error("Invalid params: token required");
// Parse token string - may include npub# prefix
let tokenValue = tokenString;
if (tokenString.includes('#')) {
tokenValue = tokenString.split('#')[1];
}
const token = await prisma.token.findUnique({
where: { token: tokenValue },
});
if (!token) {
const result = JSON.stringify({
valid: false,
reason: "Token not found",
});
return admin.rpc.sendResponse(req.id, req.pubkey, result, NDKKind.NostrConnect);
}
// Check if token is revoked (soft deleted)
if (token.deletedAt) {
const result = JSON.stringify({
valid: false,
reason: "Token has been revoked",
});
return admin.rpc.sendResponse(req.id, req.pubkey, result, NDKKind.NostrConnect);
}
// Check if token is expired
if (token.expiresAt && token.expiresAt < new Date()) {
const result = JSON.stringify({
valid: false,
reason: "Token has expired",
});
return admin.rpc.sendResponse(req.id, req.pubkey, result, NDKKind.NostrConnect);
}
// Token is valid
const result = JSON.stringify({
valid: true,
key_name: token.keyName,
client_name: token.clientName,
expires_at: token.expiresAt,
redeemed: token.redeemedAt !== null,
});
return admin.rpc.sendResponse(req.id, req.pubkey, result, NDKKind.NostrConnect);
}