@bitcoinerrorlog/pubky-shop (英语)
用于Pubky Marketplace 库存 HTTP 合同的SDK类型,
确定性JSON/CSV交换和持久的进口规划
pubky-shop 销售商CLI和一通Shopify桥。 一揽子措施仅限无害环境管理,而且
需要节点22或更新。 现公布于npm
@bitcoinerrorlog/pubky-shop (单位:千美元)latest (单位:美元) publish.yml 工作流程
当 GitHub 发布时.
npm install @bitcoinerrorlog/pubky-shop
npx pubky-shop --help
它所谈的服务
pubky/pubky-marketplace-service· ;
其 HTTP 路由记录在
docs/api.md。 。 。 .
软件包出口
.是浏览器安全条目: 解码器,PubkyShopClient(编一清单) 和波浪 3a HTTP),以及内嵌入式进口规划器(planImport, (中文(简体) ),planImportStream, (中文(简体) ),MemoryManifestStore, (中文(简体) ),resumeTasks,块sync-many帮助者)。 它与Web Crypto兼容的SHA-256相接,从未 进口node:或者说@synonymdev/pubky。 。 。 ../node是节点池规划器 :FileManifestStore,磁盘备份planImport编号 :planImportStream, (中文(简体) ),resumeTasks,以及streamResumeTasks。 。 。 .@synonymdev/pubky是仅由 CLI 使用的可选对等点 /./node。 。 。 .
import {
MemoryManifestStore,
PubkyShopClient,
planImport,
} from "@bitcoinerrorlog/pubky-shop";
import { FileManifestStore, planImport as planImportNode } from "@bitcoinerrorlog/pubky-shop/node";
证书所有权
import { PubkyShopClient } from "@bitcoinerrorlog/pubky-shop";
const client = new PubkyShopClient({
session: process.env.PUBKY_MARKETPLACE_SESSION!,
serviceUrl: "https://marketplace.example/",
});
serviceUrl 市场服务来源(生产:
https://marketplace-service-production-ce23.up.railway.app) (中文(简体) ). 每一种方法
返回一个 SdkResult<T>, (中文(简体) ), { ok: true, value } 或者说 { ok: false, error }, (中文(简体) ),
并且不为服务或运输故障投放:
const result = await client.listings(sellerPubky, { limit: 50 });
if (!result.ok) {
console.error(result.error.code); // for example "session_rejected"
} else {
console.log(result.value);
}
主持人得到了不透明 服务员出带, 拥有坚持, 期满政策,办理续签,撤销,账务约束,签收清理等手续. 这个 SDK: (英语)
- 发送
Authorization: Bearer仅用于验证的HTTPS服务源; - 拒绝用户信息、查询、碎片、非根路由和非HTTPS服务 URL;
- 绝不循规蹈矩,绝不隐匿地更新被否决的会话;
- 返回静态
session_rejectedhTTP 401 错误; - 永不记录、串行、坚持、返回或拖延携带者;
- 绝不接受销售者的秘密密钥、种子、根键或密钥.
ServiceAuthTokenSigner 是一个只有接口的未来主机边界。 它回来了
主机批准的 AuthToken 明信片字节和预期的阴暗字节 。 这个包
不执行 Ring, 密钥存储, 主服务器会话薄荷, AuthToken
交换或自动无记名更新。 服务 AuthToken/ 持有者是分开的
任何家庭服务员的证书.
库存客户
getInventoryProjection(aggregateId) 财务报告和审定财务报表 adjustInventory(request) 返回时
SdkResult<T>。它们解码生成的"一波"合同,同时保留
前进相容性未知响应字段。 客户端绑定 fetch 改为
全球对象 因此铬 Window.fetch 不被援引为一种方法。 波浪3a卖家HTTP开机
同一类: listings, (中文(简体) ), orders, (中文(简体) ), events, (中文(简体) ), getListing, (中文(简体) ), syncMany
(满分100分),网络呼和会. createSession POSTs Authtoken 字节
作为 application/octet-stream 并且不附载任何携带者。 第1波粗点 i64 字段
(单位:千美元)server_revision 和每批库存数量)
bigint,包括普通小值。 JSON代号被俘获
在 Java 脚本之前 Number 转换, 已签名的64位区域以外的值
和非整数符号失败 invalid_response,和未知的整数字段
也作为无损失保留 bigint。 。 。 .
InventoryAdjustRequest.expected_revision 财务报告和审定财务报表 delta 为: bigint. SDK 软件
序列化它们为精确的未引用的 JSON 整数符号; 例如
expected_revision: 9007199254740992n 发送
"expected_revision":9007199254740992反应机构仍受约束,
服务器消息从不反映,只允许列出服务错误代码
被暴露出来.
预测 stock.authority 实值 listing_total。在变体跟踪上
列出投影带 variants,每个大小一行
(单位:千美元)variant_id选项 sku, (中文(简体) ), enabled, (中文(简体) ), total, (中文(简体) ), available, (中文(简体) ), reserved, (中文(简体) ),
sold, (中文(简体) ), sold_out),解码并验证.
InventoryAdjustRequest.variant (单位:千美元){ id?, sku? })选择一个大小并是
(d) 服务要求列入有变式的列表。 它的答案带有
stock.authority: "variant" (单位:千美元)VariantStockView:大小的计数器外加
列出总数 listing_total); 单变量列表仍然答案
listing_total缩小 stock.authority 读取前 variant_id。 。 。 .
| 方法 | 服务路线 |
|---|---|
getInventoryProjection(aggregateId) | GET /v1/inventory/listings/{aggregateId} |
adjustInventory(request) | POST /v1/inventory/adjust |
listings(pubky, query?) | GET /v1/sellers/{pubky}/listings |
orders(pubky, query?) | GET /v1/sellers/{pubky}/orders |
events(pubky, query?) | GET /v1/sellers/{pubky}/events |
getListing(seller, listingId) | GET /v1/listings/{seller}/{listingId} |
syncMany(listings) | POST /v1/listings/sync-many (满分100分) |
addWebhook(url) | POST /v1/webhooks |
rotateWebhook(id) | POST /v1/webhooks/{id}/rotate |
deleteWebhook(id) | DELETE /v1/webhooks/{id} |
listSessions() | GET /v1/auth/sessions |
createSession(authToken) | POST /v1/auth/sessions |
updateSession(id, patch) | PATCH /v1/auth/sessions/{id} |
revokeSession(id) | DELETE /v1/auth/sessions/{id} |
被绑定的可执行合同是
test/fixtures/service/inventory.json字节
pubky/pubky-marketplace-service 订正
4d5c07c0f273616c4fba06697f90d4baef5a7722迁移 0034见
源代码和SHA-256的详细信息.
决断 JSON
canonicalJson执行 RFC 8785 JCS 文本.encodeCanonicalJson发射UTF-8 正好有一个LF.parseBoundedJson拒绝无效的 UTF-8, 重复对象名称, 过多 字节/深度/节点/字符串大小,和不支持的Unicode.decodeExportEnvelope编号 :encodeExportEnvelope保存未知的信封, 在保留服务投影的同时,列表-收发器和投影字段 字段出自卖方授权的记录.captureSignedRecord保留精确的签名记录字节和一个SHA-256 侧车.emitSignedRecord(capture)用于未修改记录的字节相同. 更改记录需要主机注入生产计划验证器,并且是 然后JCS连载。 拒绝验证不执行写入 .
JSON编解码器从未将服务预测合并为已签名的记录.
RFC 4180 CSV 标准
exportCanonicalCsv(rows, { excelBom?: boolean }) 写一个强制性标题,
引用的 UTF-8 单元格、 CRLF 记录、 确定性列
和排队命令, 和Canonic JSON巢穴细胞。 正常输出没有BOM;
清晰的 Excel 选项发出一个。 危险的电子表格前缀
(单位:千美元)=, (中文(简体) ), +, (中文(简体) ), -, (中文(简体) ), @)和领先的负极点使用可逆的负极点
逃脱.
parseCanonicalCsvStream(source, onRow, limits) 是未绑定目录字节
API (英语). source 也许是 AsyncIterable<Uint8Array>页:1
ReadableStream<Uint8Array>,或同步流动。 递增
hashes source字节,解码UTF-8,即使其三个字节也承认 BOM
分别到达,并保留 RFC 4180 状态 跨块分块 CRLF,
逃脱了引用, 和多字节字符。 它只保留当前界限
行/单元格和报告测量了峰值解析器拥有的字节。 跨行复制和
列表组验证由 planImportStream 承诺之前.
parseCanonicalCsv(bytes) 是受约束的、可实现的便利编码器。 这个
接受 BOM 或 没有 BOM 并拒绝单独 LF/CR 、 简略引用、 重复
头/行/变位代号,模棱两可的 SKU, 相互冲突的列表字段, 原始
公式有效载荷、无效身份/映射、不安全整数和超限
输入。 未知的额外列被保留在 extraFields 并导出
决了.
条形柱为:
record_uri, (中文(简体) ), seller_pubky, (中文(简体) ), listing_id, (中文(简体) ), source_listing_key, (中文(简体) ),
record_revision, (中文(简体) ), variant_id, (中文(简体) ), sku, (中文(简体) ), state, (中文(简体) ), title, (中文(简体) ), description, (中文(简体) ),
taxonomy_json, (中文(简体) ), category, (中文(简体) ), condition, (中文(简体) ), tags_json, (中文(简体) ), amount_minor, (中文(简体) ),
currency, (中文(简体) ), exponent, (中文(简体) ), variant_quantity, (中文(简体) ), variant_enabled, (中文(简体) ),
options_json, (中文(简体) ), media_json, (中文(简体) ), shipping_options_json, (中文(简体) ),
return_policy_json, (中文(简体) ), sale_json,以及 external_refs_json。 。 。 .
身份只来自 record_uri, (中文(简体) ), (seller_pubky, listing_id),或一个
明确 source_listing_key 为了新的记录。 标题永远不是身份.
流出输入没有固定的总字节或总行上限. 行字节, 单元格
字节、列、嵌入式 JSON 深度和剖析器/平面工作套集被限制
失败时输入安全观测值。 字节组合方便解析器
出口者还保留了明确的总字节/行盖.
持久的进口规划
浏览器主机针对内存的计划 ManifestStore (Shop供应德克西):
import {
MemoryManifestStore,
browserFileSource,
planImportStream,
resumeTasks,
} from "@bitcoinerrorlog/pubky-shop";
const store = new MemoryManifestStore();
const planned = await planImportStream(browserFileSource(file), { store });
planImport 编号 : planImportStream 打开 . 带有 Web API 的流派, 绑定
工作集(64个 MiB 便利/ 分析平面字节),并调用 store.create
仅在EOF、UTF-8/CSV/JSON/映射验证、身份索引核对和
来源 SHA-256 完成. 解析失败会留下零行. JSON是一个界限
便利路径( e)[{…}] 或者说 {rows:[…]}; CSV 为流. 同上,注:
是来自SHA-256的UUID v5相式的图案,显式标识,行名,以及
常态散列——与节点规划器相同的字节. chunkSyncManyListings
拆分发布批次100. classifySyncManyItem 读取 207 个结果.
节点主机保留磁盘集合规划器 :
import {
FileManifestStore,
planImportStream,
replayImport,
resumeTasks,
} from "@bitcoinerrorlog/pubky-shop/node";
const store = new FileManifestStore("/secure/host-owned/import-manifests");
const planned = await planImportStream(fileReadable, { store });
计划递增地写一个模式0600 spoll和外部分组索引 在主机提供的列表目录中。 外部结合类型 验证重复行、变体身份、 SKU 和列表级别的事实 不保留已解码源或进程内存中的所有行。 第一个 已承诺的表写只发生在EOF,UTF-8/CSV/映射验证之后, 外部分组、生成-ID碰撞检查和源SHA-256 已完成。 错误的后期输入会去掉规划的集合并留无 显出.
一份清单可以修正其编号 准确来源 SHA-256和十进制源字节数,
解析器/映射/schema 版本, 完整的不可移动行身份, 正常化
排行式散列、动作、生成列表标识和确定性同位素
键。 JSONL 运单被流到一个 fsynced 临时文件和
在解剖学上更名为. loadSummary 财务报告和审定财务报表 streamRows 避免实现;
load 财务报告和审定财务报表 planImport(bytes, ...) 明确设定便利 API.
streamRows 验证完整的文件并跟踪行数
输出任何权威行. checkpointImportRow 执行边框
流体原子重写,以及 streamResumeTasks 恢复任意行的目录
计数不调用 load. 生成的标识在将来仍然存在
出版社可以采取行动.
FileManifestStore 是包含在此中的生产主机提供适配器
软件包。 它能将配置的根一次化, 把它的装置,inode,
和模式,并验证该身份 锁前后,显示,集合,
检疫和清理行动。 最后打开时使用节点所在的无跟随旗
曝光它们; 文件为模式 0600, root 和规划目录为模式
0700, 并写入进程间排除、 fsync 和原子重命名或
附录.
这不是故意的 openat 监禁要求: 节点没有
目录 - 相对无后 API 。 主机配置和动画
root 的父重命名不能被同时重命名
攻击者。 检测到的根替换失败, 但有一个特权
无法避免的检查/打开缺口位于
适配器的威胁模型. 信任的母体中的符号链接是可读的; a
symlink 作为已配置的最终根或管理的最后文件被拒绝 .
废弃的死活程序 .planning 财务报告和审定财务报表 .tmp 文物只有在以后才能收获
配置年龄,同时使用 live-PID, 年轻, 更改身份, 以及未知文件
页:1.
每行检查站 planned, (中文(简体) ), publishing, (中文(简体) ), published_unsynced, (中文(简体) ),
complete, (中文(简体) ), conflict,以及 failed重新绘制不确定的地图 publishing
行改为 reconcile_publish绝不是盲目的; published_unsynced 恢复
只能是服务同步腿.
replayImport 返回同一行身份的现有显示,并
胡说八道 更改的内容记录在一个单独的不可改变的
pubky-shop-replay-quarantine JSONL 日志本身的单调版本和一个
与表单版本进行比较和补充检查。 身份为
SHA-256(manifest schema/version, replay source SHA-256, canonical conflict hash): 相继、相并和重现后重复播放返回
现有持久记录,但不添加版本。 元数据记录被绑定
并附随 O_APPEND冲突排居其中,
内容验证 JSONL 侧车,并随读 streamReplayConflicts。 。 。 .
既不附加也不读取重写或实现以前的历史.
D6.19 保留为主机操作:保留显示/结果和隔离文件
至少30天,然后打电话 compactReplayQuarantines 保留
断取. 接合是明确界限的流体维护操作; 3;
在身份年限过后,后期重播可能会产生新的审计记录.
因此存储以主机保留回放音量为界,而不是以
不安全的进程封顶 。 断接的隔离尾巴在主机关闭前失效
电话 repairReplayQuarantineTail,验证每一个完整的记录
只去除不完整的最后碎片. discardManifest 这是
版本 CAS 丢弃控制; 它首先使显示的不可用, 然后
移除其保留的隔离/冲突文件。 重放永不改变
complete, (中文(简体) ), conflict, (中文(简体) ), failed,或任何其他行检查站。 检疫
报告存活了一个新的 FileManifestStore 举个例子 CSV 格式错误或截断
创造任何迹象。 策划者自己没有做家庭服务员 PUT,假的
比较和扫描,或服务出版物;CLI listings import 命令
上面还有Shofify Bridge 驱动出版物.
外部分组只保留一个固定的扇入分批. 生成运行使用
定型生成/索引名称而非内相路径目录.
每个输入的字节预算费用固定为64个KiB流/读取行/解码器
高通、行头、路由器、路径名和输出元数据;扇入是
预算允许的最低限额和明确描述上限
(单位:千美元)maxSortOpenFiles,默认16。 报告的资源使用情况包括:
配置了上限和测量描述符/元数据/工作设定高水分标记.
无法支持双向合并的配置在之前被拒绝
读取输入.
安全错误和限制
PubkyShopError 使用静态消息。 细节中只包含被绑定的数字,
字段名称、允许列表的服务代码、显示身份和行身份.
接收器值、运输例外文本、服务器消息/机体和源
单元格文本除外.
错误代码 :
invalid_configuration, (中文(简体) ), invalid_service_url, (中文(简体) ), invalid_session, (中文(简体) ),
origin_violation, (中文(简体) ), session_rejected, (中文(简体) ), transport_error, (中文(简体) ),
response_limit_exceeded, (中文(简体) ), invalid_response, (中文(简体) ), service_error, (中文(简体) ),
invalid_json, (中文(简体) ), unsupported_json_value, (中文(简体) ), limit_exceeded, (中文(简体) ), malformed_csv, (中文(简体) ),
invalid_csv_header, (中文(简体) ), duplicate_row, (中文(简体) ), duplicate_variant_id, (中文(简体) ),
ambiguous_sku, (中文(简体) ), conflicting_listing_fields, (中文(简体) ), formula_payload, (中文(简体) ),
invalid_identity, (中文(简体) ), invalid_mapping, (中文(简体) ), validation_failed, (中文(简体) ),
unsupported_record_version_or_field, (中文(简体) ), manifest_conflict, (中文(简体) ),
manifest_store_error,以及 changed_replay_quarantined。 。 。 .
销售商CLI
pubky-shop 是卖方命令行客户端。 船舶违约就是生产
来源( e)https://shop.pubky.app 财务报告和审定财务报表
https://marketplace-service-production-ce23.up.railway.app) (中文(简体) ). 覆盖
--bff-url 编号 : --service-url, (中文(简体) ), PUBKY_SHOP_BFF_URL 编号 : PUBKY_SHOP_SERVICE_URL, (中文(简体) ),
或者说 $XDG_CONFIG_HOME/pubky-shop/config.json 密钥 bff_url 财务报告和审定财务报表 service_url
(旗帜击败env击败文件).
市场登录使用商店BFF CLI赠款路线. CLI 生成
result_cpk 编号 : result_delivery_id,以
一个家用服务器 PoP PUT, 并且从来没有持有商店饼干或 BFF 签名密钥。 登录
将补助金绑定在主服务器的阴暗会话上。 无头证明( CI 和活
薄荷能装上弹道座椅,然后呼叫 @synonymdev/pubky 0.11 (简体中文)
Signer.approveAuthRequest 编辑 pubkyauth://signin_grant URL 这样SDK
补助金申请. @synonymdev/pubky 0.8 将 AuthToken 张贴在该收件箱上
而受赠的劳动者 grant_invalid经批准后, auth login --complete 门票并申请服务员. auth login 装入存储
主服务器会话覆盖 /pub/pubky.app/marketplace/:rw 从密钥链
服务 pubky-shop账户 {origin}|{pubky}|homeserver-session,或从
模式 0600 文件在 PUBKY_SHOP_CREDENTIAL_DIR / 配置证书
目录。 有效载荷是 {pubky,capabilities,secret} 地点 secret 实值
Session.exportLocalSecret()。丢失的物品是出口2
homeserver_session_missing无法读取或无法操作的材料为出口2
homeserver_session_invalid市场持有人是一个单独的项目,
账户 {origin}|{pubky}索赔不退回会议编号; auth logout
需求 --force-local 除非有UUID会话 id .
PUBKY_SHOP_LIVE=1 npm test -- test/cli.live.test.ts
pubky-shop auth login --json --complete
pubky-shop auth status --json
pubky-shop listings export --format json --output listings.json
pubky-shop listings import --input listings.json
pubky-shop orders export --json
pubky-shop events tail --json
pubky-shop webhook add --url https://example.invalid/hook
pubky-shop webhook rotate --id <webhook-id>
pubky-shop webhook delete --id <webhook-id>
pubky-shop auth logout --force-local
--json 指纹 {ok,data,error{code,message}}退出时 0 成功吗, 1 用途,
2 授权/拒绝, 3 远程/ 速率限制/ 无法使用.
网络呼号
以 pubky-shop webhook add --url <https-url> 或者说
client.addWebhook(url)· ; rotateWebhook 编号 : webhook rotate 发行新的
秘密和密钥标识,以及 deleteWebhook 编号 : webhook delete 删除
终点 服务用这些信头标出每一次交付:
| 页眉 | 数值 |
|---|---|
Pubky-Webhook-Version | 1 |
Pubky-Webhook-Id | 事件编号( UUID) |
Pubky-Webhook-Timestamp | Unix 秒数 |
Pubky-Webhook-Key-Id | 结尾当前密钥 ID( UUID) |
Pubky-Webhook-Signature | v1= 外加小写 HMAC-SHA256 |
HMAC是计算出来的 v1.{timestamp}.{event id}.{raw body} 键入
秘密的SHA -256字节 其中的秘密是未加的基数64url
创建或旋转终点时返回字符串。 对照
生请求字节,不重序 JSON. verifyPubkyWebhook (只有节点,
从 Shopify 连接器条目中导出)检查密钥 ID, 时间戳
恒定时间 skew, 签名格式和签名 :
import { verifyPubkyWebhook } from "@bitcoinerrorlog/pubky-shop/connectors/shopify";
const verdict = verifyPubkyWebhook({
raw: rawBodyBytes, // Uint8Array of the exact request body
secretBase64Url: process.env.PUBKY_WEBHOOK_SECRET!,
expectedKeyId: process.env.PUBKY_WEBHOOK_KEY_ID!,
eventId: headers["pubky-webhook-id"],
timestamp: headers["pubky-webhook-timestamp"],
keyId: headers["pubky-webhook-key-id"],
signature: headers["pubky-webhook-signature"],
nowSeconds: Math.floor(Date.now() / 1000),
maxSkewSeconds: 300,
});
if (!verdict.ok) {
// verdict.reason: "malformed" | "stale" | "wrong_key" | "bad_signature"
}
重复交付 Pubky-Webhook-Id。 。 。 .
商店桥
@bitcoinerrorlog/pubky-shop/connectors/shopify 地图
购买产品 CSV 头和 products/update 编号 :
inventory_levels/update {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}然后进入CSV线
驱动现有的客户端: homeserver PUT, syncMany, (中文(简体) ), inventory.adjust
与 external_ref.channel shopify卖方 events,和 pubky 网络hook
核查。 CSV数量栏记作损失. map-csv 已经
不要把它们写成 犬类股票。 管理 API 客户端会说 GraphQL
inventorySetQuantities 与比较数量。 测试结果与
有记录的答复。 现场商店 纪念品 和网络商店的终点是
记录 connectors/shopify-bridge/BOUNDARY.md。 。 。 .
shopify-bridge map-csv --input products.csv --seller <pubky> --currency USD --exponent 2 --output canonical.csv --losses losses.json
shopify-bridge config-summary --secrets bridge-secrets.json
shopify-bridge webhook --secrets bridge-secrets.json --receipts ./receipts --topic products/update --shop-domain shop.myshopify.com --webhook-id <id> --event-id <id> --triggered-at <iso> --hmac <base64>
webhook 恢复存储的主服务器会话( r)PUBKY_SHOP_PUBKY 编辑
CLI 证书存储)并用 storage.putBytes。 。 。 .
--put-dir 被拒绝。 秘密文件有行政令牌和普比
市场会议. config-summary 打印商店域和销售者
只有阴道。 这个 . 导出不导入此节点条目.
发展大门
运行时间依赖关系( E)@noble/curves, (中文(简体) ), qrcode)属于CLI.
@synonymdev/pubky 是可选的对等点 ./node 还有CLI 这个 .
导出不导入它们.
npm run format:check
npm run lint
npm run typecheck
npm test
npm run test:full
npm run build
npm run consumer:check
npm run browser:check
npm run pack:dry
npm run gate
npm run gate:full
npm test 编号 : npm run gate 保留仍会溢出到磁盘的 10k-row 目录 .
GATE_FULL=1 npm test (或 npm run test:full 编号 : npm run gate:full添加
100001-row目录. consumer:check 财务报告和审定财务报表 browser:check 导入已建
包装消费者的方式.
npm run pack:dry 验证包内容而不发布.