/**
 * MCP pre-signed asset upload — STEP 1 of 3.
 *
 * Validates the request, resolves the target folder, signs a PUT URL the
 * agent uploads to directly, and mints an HMAC token the agent later passes
 * back to `finalizeAssetUpload`. Bytes never traverse the model context.
 *
 * Authz: `canWriteRepo` on the resolved repo. For the default-home case
 * (`input.repo` omitted) this lands on the workspace_wide Assets store,
 * which grants write to any authed user. Finalize re-checks `canWriteRepo`
 * because a 15-min token outlives a folder-access revoke.
 *
 * Mime + filename are pinned at presign:
 *   - mime: only registry presign-safe raw assets pass (raster images and
 *     font files — `presignMimeAllowlist()`). SVG is excluded because it carries
 *     `sanitize: 'svg'` and the app never holds the bytes on this path, so it
 *     can't sanitize (V2 — SVG goes through the inline-bytes tool). The chosen
 *     mime is pinned into the PUT signature so the agent must send a matching
 *     Content-Type header or R2 rejects with SignatureDoesNotMatch — the
 *     wire-level guarantee behind "no SVG polyglots."
 *   - filename: validateFilename() (path-traversal / hidden / forbidden /
 *     length cap) → safeFilename() (key-segment safety). Both shared with
 *     the in-process upload path via services/assets/base.ts.
 *
 * See ~/.claude/plans/mcp-presigned-asset-upload.md.
 */
import type { WorkspaceManager } from '../core/workspace-manager.js';
import type { AuthService, AuthUser } from './auth-service.js';
/**
 * MIME types accepted by the presign path. Historically `'image/png' |
 * 'image/jpeg'`; now whatever the format registry declares presign-safe
 * (`presignMimeAllowlist()`). Kept as `string` at the type level because the
 * authoritative gate is the runtime allowlist check below — the registry is the
 * single source of truth, not a hand-maintained union that would drift from it.
 */
export type AssetPresignMime = string;
export interface PresignAssetInput {
    workspaceManager: WorkspaceManager;
    authService: AuthService;
    user: AuthUser;
    /** Target repo. Omit → default to the workspace_wide Assets store
     *  (resolved lazily, created on first use). */
    repo?: string;
    /** Owning entity. Omit → asset is self-owned: ownerType='asset',
     *  ownerId=assetId. */
    entity?: {
        type: string;
        id: string;
    };
    filename: string;
    mimeType: AssetPresignMime;
}
export interface PresignAssetOutput {
    assetId: string;
    /** Pre-signed PUT URL. Bytes go directly here; the app server never sees
     *  them. Expires in 15 min. */
    uploadUrl: string;
    /** Headers the agent must set verbatim on the PUT (notably Content-Type
     *  which is pinned into the signature). */
    headers: Record<string, string>;
    /** HMAC token the agent passes to finalize_asset_upload. */
    token: string;
    /** ISO timestamp the upload URL + token expire at. */
    expiresAt: string;
    /** Resolved target repo (useful for the MCP tool description / debugging). */
    repo: string;
}
export declare function presignAssetUpload(input: PresignAssetInput): Promise<PresignAssetOutput>;
