/**
 * MCP pre-signed asset upload — STEP 3 of 3.
 *
 * The agent has PUT bytes to the pre-signed URL minted by presign; this
 * verifies the upload landed, validates content-type + size at the wire,
 * promotes the blob from `pending/` to canonical keyspace, creates the
 * asset entity, and writes the ownership index row.
 *
 * Layered guarantees (every one mapped to a plan decision):
 *  - Tamper-proof (T2):    verifyAssetUploadToken throws TokenInvalidError on
 *                           tamper / wrong-secret / expiry.
 *  - Identity-pin (R1):    String(user.id) === payload.uploaderUserId.
 *                           Leaked token cannot be replayed by another
 *                           folder-writer (and workspace owner is NOT exempt).
 *  - Idempotent (plan):    assetIndex.get(assetId) → existing row's URL.
 *                           Safe retries on transient network errors at the
 *                           agent's end.
 *  - Authz freshness:      Re-check canWriteRepo. 15-min token outlives a
 *                           folder-access revoke.
 *  - Wire-level validation: HEAD pending and assert stored Content-Type
 *                           matches the token's `mime`, and Content-Length
 *                           ≤ 20MB. On mismatch, delete pending immediately
 *                           so the user doesn't get charged for it.
 *  - Atomic-ish promote:   r2.copy (pending → canonical) is server-side.
 *  - Compensating delete (R5): if entity-create OR index.put throws AFTER
 *                           the canonical copy succeeded, delete the
 *                           canonical blob so we don't leave a body-less
 *                           asset entity OR an entity-less blob. If THAT
 *                           also fails, log CRITICAL with the orphaned key.
 *  - Audit log (R3):       single structured line at every outcome (success
 *                           and each reject reason). Forensics + post-
 *                           incident reconstruction.
 *
 * See ~/.claude/plans/mcp-presigned-asset-upload.md.
 */
import type { WorkspaceManager } from '../core/workspace-manager.js';
import type { AuthService, AuthUser } from './auth-service.js';
export interface FinalizeAssetInput {
    workspaceManager: WorkspaceManager;
    authService: AuthService;
    user: AuthUser;
    /** HMAC token minted by `presignAssetUpload`. */
    token: string;
    /** Optional display name for the asset entity. Defaults to a title-cased
     *  version of the filename stem. */
    name?: string;
}
export interface FinalizeAssetOutput {
    assetId: string;
    /** `/api/assets/{assetId}/{filename}` — the proxied URL that resolves
     *  per-request to a short-lived signed R2 URL via the asset-api route. */
    url: string;
    ownerType: string;
    ownerId: string;
    /** Resolved repo (echoed from the token for the MCP tool to surface). */
    repo: string;
}
export declare function finalizeAssetUpload(input: FinalizeAssetInput): Promise<FinalizeAssetOutput>;
