feat: 기능 추가 과정중

This commit is contained in:
donghyeon-ka
2026-07-30 15:58:20 +09:00
parent d3ef801fe6
commit 6c52cdb916
648 changed files with 126325 additions and 6680 deletions
@@ -0,0 +1,273 @@
import type {
PresignedTransferBinding,
PresignedTransferCapability,
PresignedTransferCapabilityReceipt,
PresignedTransferMethod,
PresignedTransferReplayGuard,
} from "../../../application/ports/browser-transfer/presigned-transfer.ts";
import type { BrowserDataResult } from "../../../application/ports/browser-file-storage/shared.ts";
import {
browserDataFailure,
browserDataSuccess,
} from "../../browser-file-storage/result.ts";
export type PresignedHeaderBinding = Readonly<{
name: string;
value: string;
}>;
export type PresignedCapabilityRegistration = Readonly<{
capabilityReceipt: PresignedTransferCapabilityReceipt;
method: PresignedTransferMethod;
binding: PresignedTransferBinding;
href: string;
origin: string;
path: string;
allowedQueryParameters: readonly string[];
requestHeaders: readonly PresignedHeaderBinding[];
requiredResponseHeaders: readonly PresignedHeaderBinding[];
digestRequestHeader: string | null;
digestResponseHeader: string | null;
receiptResponseHeader: string | null;
expectedStatus: number;
expectedResponseByteLength: number | null;
mediaType: string;
byteLength: number;
maxBytes: number;
expectedSha256: string;
expiresAtEpochMs: number;
}>;
export type PresignedCapabilityBinding = Readonly<
PresignedCapabilityRegistration & {
capability: PresignedTransferCapability;
}
>;
export interface PresignedCapabilityVault {
register(
registration: PresignedCapabilityRegistration,
): BrowserDataResult<PresignedTransferCapability>;
resolve(
capability: PresignedTransferCapability,
): BrowserDataResult<PresignedCapabilityBinding>;
/**
* Atomically retires an exact identity after its single-use replay claim.
* The caller may keep the already-resolved binding on its stack for the
* in-flight request, but the vault must no longer retain or resolve it.
*/
consume(
capability: PresignedTransferCapability,
): BrowserDataResult<true>;
/**
* Best-effort, idempotent retirement for an unused or abandoned identity.
*/
revoke(capability: PresignedTransferCapability): void;
dispose(): void;
}
export function createPresignedCapabilityVault(options: Readonly<{
maxActiveCapabilities: number;
now?: () => number;
}>): PresignedCapabilityVault {
if (
!Number.isSafeInteger(options.maxActiveCapabilities) ||
options.maxActiveCapabilities < 1
) {
throw new TypeError("Presigned capability vault limit is invalid.");
}
const maxActiveCapabilities = options.maxActiveCapabilities;
const now = options.now ?? Date.now;
const byIdentity =
new WeakMap<PresignedTransferCapability, PresignedCapabilityBinding>();
const byReceipt =
new Map<PresignedTransferCapabilityReceipt, PresignedTransferCapability>();
let disposed = false;
function pruneExpired(): void {
const current = now();
if (!Number.isSafeInteger(current)) return;
for (const [receipt, capability] of byReceipt) {
if (capability.expiresAtEpochMs <= current) {
byReceipt.delete(receipt);
byIdentity.delete(capability);
}
}
}
function revoke(capability: PresignedTransferCapability): boolean {
try {
const binding = byIdentity.get(capability);
if (!binding) return false;
byIdentity.delete(capability);
if (byReceipt.get(binding.capabilityReceipt) === capability) {
byReceipt.delete(binding.capabilityReceipt);
}
return true;
} catch {
return false;
}
}
return Object.freeze({
register(
registration: PresignedCapabilityRegistration,
): BrowserDataResult<PresignedTransferCapability> {
if (disposed) {
return browserDataFailure("UNAVAILABLE", "PRESIGNED_TRANSFER");
}
pruneExpired();
if (
byReceipt.has(registration.capabilityReceipt) ||
byReceipt.size >= maxActiveCapabilities
) {
return browserDataFailure(
byReceipt.has(registration.capabilityReceipt)
? "CONFLICT"
: "LIMIT_EXCEEDED",
"PRESIGNED_TRANSFER",
byReceipt.has(registration.capabilityReceipt)
? { recovery: "REISSUE_CAPABILITY" }
: undefined,
);
}
const capability = Object.freeze({
capabilityReceipt: registration.capabilityReceipt,
method: registration.method,
binding: freezeBinding(registration.binding),
mediaType: registration.mediaType,
byteLength: registration.byteLength,
maxBytes: registration.maxBytes,
expectedSha256: registration.expectedSha256,
expiresAtEpochMs: registration.expiresAtEpochMs,
}) as PresignedTransferCapability;
const binding: PresignedCapabilityBinding = Object.freeze({
capability,
capabilityReceipt: capability.capabilityReceipt,
method: capability.method,
binding: capability.binding,
href: registration.href,
origin: registration.origin,
path: registration.path,
allowedQueryParameters: Object.freeze([
...registration.allowedQueryParameters,
]),
requestHeaders: freezeHeaders(registration.requestHeaders),
requiredResponseHeaders: freezeHeaders(
registration.requiredResponseHeaders,
),
digestRequestHeader: registration.digestRequestHeader,
digestResponseHeader: registration.digestResponseHeader,
receiptResponseHeader: registration.receiptResponseHeader,
expectedStatus: registration.expectedStatus,
expectedResponseByteLength:
registration.expectedResponseByteLength,
mediaType: capability.mediaType,
byteLength: capability.byteLength,
maxBytes: capability.maxBytes,
expectedSha256: capability.expectedSha256,
expiresAtEpochMs: capability.expiresAtEpochMs,
});
byIdentity.set(capability, binding);
byReceipt.set(capability.capabilityReceipt, capability);
return browserDataSuccess(capability);
},
resolve(
capability: PresignedTransferCapability,
): BrowserDataResult<PresignedCapabilityBinding> {
if (disposed) {
return browserDataFailure("UNAVAILABLE", "PRESIGNED_TRANSFER");
}
try {
const binding = byIdentity.get(capability);
return binding
? browserDataSuccess(binding)
: browserDataFailure("POLICY_REJECTED", "PRESIGNED_TRANSFER");
} catch {
return browserDataFailure("POLICY_REJECTED", "PRESIGNED_TRANSFER");
}
},
consume(
capability: PresignedTransferCapability,
): BrowserDataResult<true> {
if (disposed) {
return browserDataFailure("UNAVAILABLE", "PRESIGNED_TRANSFER");
}
return revoke(capability)
? browserDataSuccess(true as const)
: browserDataFailure(
"POLICY_REJECTED",
"PRESIGNED_TRANSFER",
);
},
revoke(capability: PresignedTransferCapability): void {
if (disposed) return;
revoke(capability);
},
dispose() {
if (disposed) return;
disposed = true;
for (const capability of byReceipt.values()) {
byIdentity.delete(capability);
}
byReceipt.clear();
},
});
}
export function createSingleUsePresignedReplayGuard():
PresignedTransferReplayGuard {
const claimed = new WeakSet<PresignedTransferCapability>();
return Object.freeze({
claim(
capability: PresignedTransferCapability,
): BrowserDataResult<true> {
try {
if (claimed.has(capability)) {
return browserDataFailure("CONFLICT", "PRESIGNED_TRANSFER", {
recovery: "REISSUE_CAPABILITY",
});
}
claimed.add(capability);
return browserDataSuccess(true as const);
} catch {
return browserDataFailure("POLICY_REJECTED", "PRESIGNED_TRANSFER");
}
},
});
}
function freezeBinding(
binding: PresignedTransferBinding,
): PresignedTransferBinding {
return binding.kind === "DOWNLOAD"
? Object.freeze({
kind: "DOWNLOAD" as const,
resourceId: binding.resourceId,
})
: Object.freeze({
kind: "UPLOAD_PART" as const,
protocol: binding.protocol,
sessionId: binding.sessionId,
requestBindingSha256: binding.requestBindingSha256,
uploadBindingSha256: binding.uploadBindingSha256,
partNumber: binding.partNumber,
offset: binding.offset,
idempotencyKey: binding.idempotencyKey,
});
}
function freezeHeaders(
headers: readonly PresignedHeaderBinding[],
): readonly PresignedHeaderBinding[] {
return Object.freeze(
headers.map((header) =>
Object.freeze({ name: header.name, value: header.value }),
),
);
}