fix(storage): correct presign content-type claim; head returns contentType

Spec review (live negative test) found s3-request-presigner unconditionally
unsigns content-type: header-less PUT returns 200, so the previous docblock
claiming signature enforcement was a false guarantee. Content-Type is now
documented as convention-only; head() returns contentType so the complete
step (Task 19) can verify it server-side against the session declaration.

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-09-17 20:35:08 +08:00
parent 37f4b3e11f
commit 8e870de9d7
3 changed files with 16 additions and 7 deletions
+7 -1
View File
@@ -9,9 +9,15 @@ export interface UploadCredential {
expiresAt: string; // ISO
}
export interface StoragePort {
/**
* 预签名上传凭证。注意:headers 为「约定必须发送」而非签名强制——SigV4 预签名
* 不含 Content-Length,且 SDK 将 Content-Type 列为不可签名头。字节核验在
* complete 阶段经 head().bytes 比对,Content-Type 一致性经 head().contentType
* 与会话申明值比对(服务端兜底,见 Task 19)。
*/
presignPut(objectKey: string, bytes: number, contentType: string, ttlSeconds: number): Promise<UploadCredential>;
presignGet(objectKey: string, ttlSeconds: number): Promise<string>;
head(objectKey: string): Promise<{ bytes: number; etag: string } | null>;
head(objectKey: string): Promise<{ bytes: number; etag: string; contentType: string } | null>;
getStream(objectKey: string): Promise<NodeJS.ReadableStream>;
put(objectKey: string, body: Buffer, contentType: string): Promise<{ etag: string }>;
/** 复制到正式键;目标已存在时校验一致性并幂等返回(禁止覆盖语义)。 */