feat(api): advance capability and secure operations slices

This commit is contained in:
chick
2026-07-17 11:57:20 +08:00
parent 8018b36adf
commit 1cc4a995ee
19 changed files with 2102 additions and 22 deletions
@@ -4,6 +4,7 @@ import type {
} from '../../application/connections/upstream-session-client.js';
import type { TransportResponse } from './safe-instance-transport.js';
import { UpstreamError } from './upstream-error.js';
import { OperationNotDispatchedError } from '../../application/operations/secure-operation-execution.js';
export interface SafeUpstreamTransport {
get(url: string): Promise<TransportResponse>;
@@ -15,6 +16,34 @@ export interface SafeUpstreamTransport {
}
export class SafeUpstreamGateway {
constructor(private readonly options: { readonly transport: SafeUpstreamTransport }) {}
async postNetworkRegisterAuto(origin: string): Promise<UpstreamResponse> {
let parsed: URL;
try {
parsed = new URL(origin);
} catch {
throw this.notDispatched();
}
if (
(parsed.protocol !== 'http:' && parsed.protocol !== 'https:') ||
parsed.username ||
parsed.password ||
parsed.pathname !== '/' ||
parsed.search ||
parsed.hash
)
throw this.notDispatched();
const url = `${parsed.origin}/api/network/register-auto`;
try {
return await this.options.transport.post(url, {}, '');
} catch (error) {
if (
error instanceof UpstreamError &&
(error.code === 'UNSAFE_ORIGIN' || error.code === 'UNSAFE_RESOLUTION')
)
throw new OperationNotDispatchedError(error.code);
throw error;
}
}
async request(request: UpstreamRequest): Promise<UpstreamResponse> {
const url = new URL(request.url);
if (url.protocol !== 'https:') throw new UpstreamError('UPSTREAM_INSECURE_AUTH');
@@ -35,4 +64,7 @@ export class SafeUpstreamGateway {
}
throw new UpstreamError('UPSTREAM_REQUEST_INVALID');
}
private notDispatched(): OperationNotDispatchedError {
return new OperationNotDispatchedError('UPSTREAM_REQUEST_INVALID');
}
}