feat(storage,g1): real-OSS support and G1 smoke — gate CLOSED
G1 (skipped at P1 for lack of credentials) executed 2026-09-21 against the user-provided bucket live-album @ oss-cn-beijing: Raw-SDK smoke (scripts/g1-oss-smoke.mjs, creds via runtime env only): - HeadBucket / presign PUT direct upload / head byte+type verify / presign GET round-trip / copy staging→originals / idempotent replay / DeleteObject cleanup — all pass. - S3-compat lifecycle query unsupported → console manual check remains the only open G1 sub-item (need: confirm no lifecycle rule hits photo-live/). Adapter-level (production path, createStorageFromEnv → real OSS): - presignPut+PUT 200, head verify, presignGet round-trip equal, copyIfAbsent idempotent (created:true→false, same etag), forbid-overwrite guard throws UPLOAD_VERIFY_FAILED — all pass. Findings locked in: - Addressing: OSS S3-compat requires virtual-host style with BASE endpoint (path-style → 403 signature mismatch). StoragePort adapter gains optional MinioStorageConfig.forcePathStyle + S3_FORCE_PATH_STYLE env (default true keeps local MinIO behavior); required-field validation fixed to string fields only (boolean false ≠ missing). - .env.production.example-cn S3 section updated to the confirmed shape (beijing endpoint/region, virtual-host, bucket live-album). Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -27,10 +27,15 @@ export function createStorageFromEnv(): MinioStorageAdapter {
|
||||
accessKey: process.env.S3_ACCESS_KEY,
|
||||
secretKey: process.env.S3_SECRET_KEY,
|
||||
bucket: process.env.S3_BUCKET,
|
||||
} satisfies Record<keyof MinioStorageConfig, string | undefined>;
|
||||
const missing = Object.entries(config)
|
||||
.filter(([, value]) => !value)
|
||||
.map(([key]) => `S3_${key.toUpperCase()}`);
|
||||
// S3_FORCE_PATH_STYLE 可选:缺省 true(MinIO path-style);阿里云 OSS 等
|
||||
// 云形态设 false(virtual-host + 基础 endpoint)——G1 实测定案。
|
||||
forcePathStyle: process.env.S3_FORCE_PATH_STYLE
|
||||
? process.env.S3_FORCE_PATH_STYLE === 'true'
|
||||
: true,
|
||||
};
|
||||
// 只校验必填字符串字段(forcePathStyle 是布尔,false 不代表缺失)。
|
||||
const required = ['endpoint', 'region', 'accessKey', 'secretKey', 'bucket'] as const;
|
||||
const missing = required.filter((key) => !config[key]).map((key) => `S3_${key.toUpperCase()}`);
|
||||
if (missing.length > 0) {
|
||||
throw new Error(`createStorageFromEnv: 缺少环境变量 ${missing.join(', ')}(S3_* 配置见仓库根 .env)`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user