跳转到内容

S3 资源

直接读写现有 S3 兼容桶,并使用项目 S3 授权面。若文件需要项目 PostgreSQL 元数据、所有者、审计证据和受管下载链接,应选择 storage。

本页核对 Viat 1.1.0 稳定版。示例使用合成值/服务桩,未执行、未连接真实服务、未发送消息。先读资源总览。

先创建桶和最小范围访问凭据,允许 API 节点访问。Test/list 需要 ListBucket,按前缀授予所需 GetObject/PutObject/DeleteObject。平台访问还需要项目授权类型 s3 上适用的规则(resource/key 属性及 read/write/delete 操作);旧权限字符串示例不是当前授权模型。

表中“必填”描述结构解析;提供方/后端的条件必填、运行时默认及限制在下节补充。null 仅在类型明确允许时可用,数字格式的存储上限不等于有意义的业务范围。不要依赖未知键被忽略来检测拼写。

字段类型/允许值必填省略默认约束含义
plain.allowed_authorizersarray<string>否;可能条件必填无显式默认;见规则—已废弃 plain S3 兼容字段,当前请求授权不使用。
plain.bucketstring是——现有桶名,不是 URL/路径。
plain.endpointstring / null否;可能条件必填null—配置的服务端点,base/操作 URL 和规范化规则依类型而定。
plain.path_styleboolean否;可能条件必填false—使用 endpoint/bucket/key,而非 bucket.endpoint/key。
plain.regionstring是——签名/操作区域,提供方规则可能要求必填。
字段类型/允许值必填省略默认约束含义
secret.access_keystring是——S3 兼容访问 key 标识。
secret.secret_keystring是——S3 兼容签名秘密。
secret.session_tokenstring / null否;可能条件必填null—可选临时 STS token,到期前轮换,不自动刷新。

bucket 必须仅为非空桶名,最长 63 字符;region 必须非空且是签名区域,不一定是 AWS 地理区域名(兼容服务可用 auto、oss-cn-hangzhou)。access_key、secret_key 不得为空白。endpoint 是服务源站,不是桶专属域名:虚拟主机方式会拒绝已经以 bucket 开头的主机。输入会裁剪 bucket/region,为无协议 endpoint 加 https://,移除末尾斜杠,空 endpoint 视为省略。省略时推导 AWS 区域服务端点。path_style 默认 false,MinIO 等需要 endpoint/bucket/key 的服务应设 true。session_token 仅供 STS 临时凭据使用,不会自动刷新。

plain.allowed_authorizers 为已废弃兼容字段,仍检查格式(非空、大小写不敏感去重),但请求时忽略。不要与仓库文件顶层 allowed_authorizers(访问同步)混淆。不要用旧权限字符串或这个已废弃 plain 字段建立新策略。

管理 API 需要平台登录及项目成员身份。列举/查看需要成员身份;创建、PUT、PATCH、Test、refresh、copy、delete 需要有效项目角色 Owner/Admin/Developer;较低权限的 operator 角色不可写。管理权限不自动赋予上游账号权限,也不替代运行时的 s3/file/行级授权。MCP 只开放其工具清单实际声明的能力,不能把资源 schema 当作完整 MCP CRUD。

  • 创建:POST /projects/{slug}/resources,请求为 {name,folder?,kind,plain,secret}。name 长度 1–64 字节且不可含 /;system 为保留名。folder 省略/空字符串表示根,非空为 [A-Za-z0-9_-]+ 段,最多 8 层/255 字节,无首尾或连续 /。
  • 资源身份为同项目 (folder,name),不是全项目裸名。同名可以位于不同文件夹。详情路由用 /resources/{name}?folder=team 显式定位;CLI 用 team/name。脚本裸引用按自身文件夹、根、全项目唯一名顺序解析,建议跨文件夹显式限定,Python 用 getattr(ctx.resources, "team/name"),TypeScript 用 ctx.resources["team/name"],而非属性链。
  • PUT 是完整替换:须重发正确 kind、完整 plain 与全部要保留的秘密值,不能从 show 的掩码恢复秘密。PATCH 的 kind 固定;省略 plain 保留,提供 plain 则整体替换(不是深合并);secret 仅逐字段覆盖,省略字段保留。移动 folder 时引用在新位置重检。
  • 清除可选秘密用 PATCH 显式 null(仅允许 null 的字段)或空字符串(仅允许空值的字段);必需/条件必需字段不能清空。清除可选 plain 字段需发送去掉该字段的完整 plain,让类型默认/缺省生效。不要用 null 代替所有类型,也不要把 *** 当作旧值。
  • $keep 是仅 PATCH/仓库同步使用的顶层 plain 字段占位符,保留服务端已有同名字段,连数字/布尔也可保留;新资源/不存在字段不能使用。嵌套 $keep 不是深合并指令。
  • 仓库文件 resources/<folder>/<name>.yaml 由路径承载 folder,name 仍是裸名。viat pull 将 secret 字段写为字符串 $secret;viat push 去掉这些占位(也接受旧 !secret 标签),对已有资源 PATCH,绝不把占位当凭据。新资源必须先安全提供实际必需秘密;占位不能创建凭据。顶层 allowed_authorizers 是仓库访问同步元数据,不要擅自塞进 plain。

$secret 占位与凭据引用不同:{"$secret":"name"} 在 config/cloud 支持位置命名另一个 secret 资源;HTTP/GraphQL 字符串头用整个 "$secret:name"。它们不等于秘密明文,保存/读取/导出保留引用,使用时解析。目标按消费资源文件夹锚定并须已存在且为 secret 类型,不能用字符串拼接插值。

公开响应含资源标识、kind、folder、plain 及秘密摘要,不返回秘密值;摘要 *** 表示该种类声明的字段,不证明每个可选凭据实际已填。plain 会原样可读/导出;secret 通过部署秘密后端加密。脚本/依赖的发布版本按快照规则冻结,uses 无 (live) 时亦冻结,不可把所有依赖描述为每次读 live;资源读取/代理操作和显式实时 secret IO 是不同边界。

1.1.0 兼容/安全限制: 实际投影仍包含 S3 access_key/secret_key/session_token。优先下列保留平台策略的代理操作,不要将 key 提取到应用代码或记录/返回资源。全部脚本依赖须按此暴露审查,受管 storage 不暴露后端凭据。

下面是创建请求 JSON,同时也是合法 YAML,可作为 resource.yaml 交给真实 CLI 命令。域名/凭据均为测试值,生产使用前须替换并完成前置条件;不要把真实 secret 文件提交仓库。

{
"name": "demo",
"folder": "",
"kind": "s3",
"plain": {
"bucket": "demo-fixtures",
"region": "us-east-1",
"endpoint": "https://s3-stub.example.test",
"path_style": true
},
"secret": {
"access_key": "fixture-access",
"secret_key": "fixture-secret-not-a-credential"
}
}
终端窗口
viat project select <slug>
viat resource create --file resource.yaml
viat resource show demo --json

等价 API 为 POST /projects/{slug}/resources(相对实例管理 API 根),请求体如上。预期得到已保存资源的公开表示和掩码摘要,不是秘密回显;示例名已存在则 409。仓库同步时去掉 folder,把配置放 resources/demo.yaml;viat push 可同步完整 plain 及未被占位过滤的 secret。创建成功不保证每个远程动作成功。

Python:get(key) 返回 bytes,get_text(key,encoding=“utf-8”) 返回文本,put(key,data,content_type=None),head(key) 返回 {exists,size,content_type,etag},另有 delete(key)、list(prefix=None,max_keys=None)。TypeScript 使用 get/getText/put/head/delete/list,put 第三个参数为 contentType。get/put 受 VIAT_S3_HELPER_MAX_BYTES 限制(默认 8 MiB),因为内容以 base64 经过 JSON 管道。download(key,dest_path)/upload(key,src_path,content_type=None) 使用服务端/worker 共享文件流式传输,不受该助手请求体上限影响;TypeScript 参数名为 destPath/srcPath/contentType。List 只取提供方一页,并非自动遍历全桶。Rust 通用 call 封装没有编码顶层 s3_op 信封,S3 应使用 binary worker 协议,不应杜撰类型化 Rust 方法。

这两个完整脚本均声明同一个根资源 demo;在获批准的测试运行中使用。写入、发送、构建和数据删除不是 dry-run。

# @resource demo
from viat import ctx
def main():
return ctx.resources.demo.head("reference/hello.txt")
// @resource demo
import { ctx } from "viat";
export async function main() {
return await ctx.resources.demo.head("reference/hello.txt");
}

Shell 没有方法装饰的 ctx.resources,仅有 JSON 环境投影;不能把上述方法名直接写成 shell 函数。binary 程序可按 worker 协议实现相应 RPC,并非自动拥有 Python/TypeScript 方法。sql 语言仅用于四种 SQL 数据源,viat_gql 仅用于 PostgreSQL/MySQL/SQLite,graphql 语言用于远程 graphql,llm 语言用于 llm;不支持的组合不会自动适配。

当测试桶已存在且获授权的 reference/hello.txt 对象时,head 返回 exists:true 和元数据,不下载内容;对象不存在时为 exists:false。本页未创建或联系测试桶。

真正发送签名的 ListObjectsV2 GET,max-keys=1,而不是部分旧注释所说的桶 HEAD。需要列举权限,可能产生请求费用,但不写对象。使用 no-proxy 客户端以保留签名头。

管理 API 使用 POST /projects/{slug}/resources/{name}/test?folder=;CLI 为 viat resource test demo。API 检查响应体 ok:连接失败通常仍为 HTTP 200 {ok:false,error:"…"},可能附 schema_warnings,不能只检查状态码。CLI 失败会非零退出。仅在允许出站/文件动作后执行。

resource.s3.empty_bucket/empty_region/empty_access_key/empty_secret_key 应补字段,bad_bucket_length 应改为桶名,endpoint_includes_bucket 应改服务源站。HTTP 403 检查策略、签名区域和 session_token 是否过期,404 检查桶/对象。助手大小错误应改用流式 download/upload,而不是重试更大的内存传输。平台 forbidden 应补 s3 授权规则,而非扩大云凭据权限。

管理错误一般为 {error,message}。DTO 的 resource.<kind>.* 经常位于 400 bad_request 的 message,而非顶层 error;不要把它们当成所有运行时助手都会返回的统一枚举。401 先恢复平台登录,403 检查有效项目角色/运行时规则,404 检查 folder/name,409 先解决同名或 resource_in_use 引用。远程拒绝与平台拒绝分开诊断,重试前判断上一次动作是否可能已生效。

在桶侧规划对象保留、版本控制和孤儿清理,临时凭据到期前应轮换。使用注入凭据的自建客户端会绕过平台授权/审计路径,应优先使用代理助手。删除资源不会删桶或对象,但会删除指向该资源的 s3 规则,避免重建同名资源继承旧授权。

通用删除步骤:先停用调用脚本、代理/CRUD 目标及相关触发器,迁移依赖并保留需要的证据,再用 viat resource delete demo 或 DELETE 详情路由。409 resource_in_use 时先重新绑定/删除消息指出的端点,不应强行绕过引用。删除配置资产不等于撤销第三方凭据、删除外部数据或回滚已发生副作用。

固定契约:contracts/1.1.0/resources.json → resource.s3。

核对实现(产品仓库相对路径):viat-core/src/types/resource.rs (KindSpec/Plain/Secret); viat-api/src/dto.rs (normalization/validation); viat-api/src/handlers/resources.rs (CRUD/Test); viat-runtime/src/resource_io.rs, resources_json.rs, python.rs, typescript.rs; viat-api/src/runner/broker.rs; viat-cli/src/main.rs and repo/resources.rs; viat-core/src/types/snapshot.rs.