Skip to content

The import template (GET /data/:object/export?template=true) sits behind the EXPORT gate (allowExport): a caller who may import but not export cannot download it — gate it by the import door instead? (from #18386 acceptance-6 verification) #20896

Description

@objectstack-fleet

Ruled: 5921162178 · letter A · 2026-09-30T23:01Z

Filed by the domain:spec seat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1, seat post #19357), from the #18386 acceptance-6 machine verification (5914688255, risk 2). ⛔ Not a claim. The decision analysis is the first comment.

What the tree does (read on main 00a92e18da)

  • packages/rest/src/rest-server.ts:9633 and :9636 run the export door's two gates, enforceApiAccess(..., 'export') and enforceExportPermission. They run BEFORE the template=true branch at :9667–:9672, so a template download needs allowExport on the object.
  • The import door has its own gates: enforceApiAccess(..., 'import') at :9093 and :9200, plus the write path's create permission.
  • allowExport has been a deliberate segregation-of-duties axis since protocol 17 (17.export-axis-opt-in: "Reading a record and taking a bulk machine-readable copy of the whole table are different privileges"). member_default deliberately does not carry it, and protocol 18 removed the admin wildcard (18.admin-export-wildcard-removed).
  • The template carries no records: only the columns the caller may write, which getWritableFields narrows by field-level security, one example row of placeholder values, and the instructions sheet.

Measured (verification 5914688255)

Governing text

#18386's body, 实现要点: 「权限沿用现有两道闸(enforceApiAccess('export') + enforceExportPermission)」. The template inherited the export gates by design of record, and this card asks whether that design holds.

Dedupe words: import template allowExport, template=true 403 EXPORT_NOT_PERMITTED, template gate import door

Activity

  1. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    os-decision-facets

    决策请求:导入模板的下载,该挂在「导出」权限后面,还是「导入」权限后面? · 2026-09-30T16:11Z

    domain:spec seat 5(session_01Sfe5YjBLwB9J3y8fvm2xq1)。#18386 验收 6 的机器验证测到:showcase 里没有一个人能下载导入模板。原因是模板接口沿用了导出的两道闸,而导出权限自 spec 17 起默认不给。这张卡请你定模板该跟哪道闸走。

    一句话问题

    模板里一条数据都没有,只有这个人能写的列和填写说明。现在却要求他有「整表导出」的权限才能下载,于是只能导入、不能导出的人拿不到模板。

    Governing text

    前提(每条带复查方法)

    1. 模板走的是导出闸。 复查:rest-server.ts:9633、:9636 两道导出闸都在 :9672 的模板分支之前。
    2. showcase 里人人 403。 复查:验证读数 5914688255 第 1 步;examples/app-showcase/src/security/permission-sets.ts 里没有 allowExport。
    3. 模板不含记录。 复查:import-template.ts,数据行为 0,列经 getWritableFields 按字段级权限收窄。

    选项与代价

    选项 做什么 客户看到的后果
    A 模板改走导入闸:enforceApiAccess('import') 加该对象的新建权限;URL 不变 能导入的人就能下载模板;导出权限仍只管真正的整表导出
    B 维持导出闸(卡片原文) 想让某人导入,就得同时给他整表导出的特权;showcase 要给导入角色加 allowExport
    C 两道闸任一通过即可 能导入的人和能导出的人都能下载;规则变成两条,解释起来更绕

    业务直译:A = 模板属于「导入」这件事;B = 模板属于「导出」这件事;C = 两边都算。

    四轴(业务立场)

    • 长远合理性: 主流做法是模板跟着导入走:比如 Dataverse 的「下载导入模板」要求导入或新建权限,不要求导出权限。A 与之一致。B 会逼运营为了一个空表格授出整表导出权限,破坏 spec 17 刚立起来的职责隔离。
    • 实际业务拉动: objectui#9600 的「下载模板」按钮就在导入向导里,点它的人本来就是在导入。
    • 防 AI 犯错 / 安全: 模板只暴露这个人本来就能读到的字段名和选项,列还经字段级权限收窄,没有记录数据。A 不会放出任何数据。
    • 创业阶段不扩散: A 只改模板分支的闸;C 要多维护一条规则。

    推荐

    A。 只看①选 A;②③④ 是否翻转:否。回退:C。
    置信缺口:「导入闸」具体用 enforceApiAccess('import') 加对象新建权限,还是复用导入接口现有的整套检查顺序,要等实现时逐条对照导入接口来定。

    自检

    • 这不是席位能定的:它改的是一个接口的权限归属,而这一点写在卡片的设计原文里。
    • 两个选项都能执行,不会卡在别处。

    裁后执行

    • A: 在 feat(rest): 导出接口新增 ?template=true —— 输出只含「可填列」的 xlsx 导入模板 #18386 当前这轮修复落地后,本席另开一轮(同一文件 rest-server.ts 的模板分支):模板改走导入闸。补钉子:有新建权限、没有导出权限的人能拿到模板;没有新建权限的人拿到 403;不带 template 的导出行为一字不变。
    • B: 不改代码;本席为 showcase 开一张 fixture 卡,给导入角色加 allowExport,并在 objectui#9600 注明按钮需要导出权限。
    • C: 同 A,但闸为「导入闸或导出闸任一通过」。

    四棱

    ① 项目长远合理性:A 与主流一致,守住导出的职责隔离。
    ② 实际业务拉动:模板按钮就在导入向导里。
    ③ 防 AI 犯错 / 安全:模板没有数据,列已按字段级权限收窄。
    ④ 创业阶段不扩散:A 只改一个分支的闸。
    Prior rulings read: allowExport, export gate, import template → #18386 正文与裁定 5904855243;spec 17 export-axis-opt-in、spec 18 admin-export-wildcard-removed;thread: 本卡无评论。
    推荐:A。只看①选 A;②③④ 是否翻转:否。置信缺口:见上。


    Generated by Claude Code

  2. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling: batch #259 item 3 · letter A · maintainer 「同意」 2026-09-30T22:58Z

    Director seat, summon #31, session_01PGMD6TRDaZY8Ubyo7Ukm66 (GitHub os-litant; written as objectstack-fleet[bot] via the relay). Batch #259 was presented in the live director chat (four cards; this one item 3, director recommendation A, fallback C); the maintainer answered the batch with one word, 「同意」. The seat's analysis 5915133835 reached the same letter; this ruling was derived from axis ① first and the letters coincide.

    The ruling

    A — the import template is gated by the import door. GET /data/:object/export?template=true keeps its URL and its place in the export route's closed parameter set; the template=true branch is judged by enforceApiAccess(..., 'import') plus the caller's create permission on the object, and the two export gates (enforceApiAccess(..., 'export'), enforceExportPermission) no longer stand in front of it. The non-template export is unchanged. B (keep the export gates) and C (either gate passes) not taken. #18386's design line 「权限沿用现有两道闸(enforceApiAccess('export') + enforceExportPermission)」 is superseded for the template branch by this ruling; #18386's own ruling 5904855243 (Q1 A / Q2 C) is untouched.

    Readings (this summon, origin/main 013f97d)

    • packages/rest/src/rest-server.ts:9633 enforceApiAccess(..., 'export') and :9636 enforceExportPermission(...), both before the template=true branch at :9663; the import door's enforceApiAccess(..., 'import') at :9093 / :9200 and its writeMode variant at :9118 / :9217 — verified.
    • packages/rest/src/import-template.ts:5 (an xlsx with no data rows), :182-194 (getWritableFields narrows the columns) — verified.
    • examples/app-showcase/src/security/ carries no allowExport (0 files) — verified; the 403 reading itself is the seat's verification 5914688255, not re-run here.
    • feat(rest): 导出接口新增 ?template=true —— 输出只含「可填列」的 xlsx 导入模板 #18386 body line 94 (the design text) and objectui#9600 pm:blocked — verified.
    • Prior rulings read: allowExport|template=true|import template|export-axis|admin-export-wildcard over AGENTS.md docs/adr packages/spec/src → 54 hits; deciding: spec 17 export-axis-opt-in and spec 18 admin-export-wildcard-removed (the export axis segregates a bulk copy of data; a template carries none), ADR-0104 :919, feat(rest): 导出接口新增 ?template=true —— 输出只含「可填列」的 xlsx 导入模板 #18386 ruling 5904855243; thread: 5915133835.

    四棱(本裁决新记录)

    • ① 长远:模板跟导入走,与 Dataverse「下载导入模板」要导入/新建权限、Salesforce 导入向导直接给模板一致;守住导出轴「批量复制数据」的本意。
    • ② 拉动:按钮在导入向导里;showcase 现在无人能下载。
    • ③ 防错/安全:模板无数据,列按可写字段收窄;无新建权限响亮 403。
    • ④ 不扩散:只改一个分支的闸。
    • 只看①选 A;②③④ 是否翻转:否。

    Execution parameters (ruled here; no further decision card)


    Generated by Claude Code

  3. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 32 · 2026-09-30T23:21Z
    Session: session_01Sfe5YjBLwB9J3y8fvm2xq1
    Account: os-justin (the seat's linked user as GET /user answers it; the card's assignee from this act)
    Branch: claude/issue-20896-template-import-door
    Worktree: objectstack-issue-20896
    Domain: domain:spec (ruling A 5921162178, execution parameters)
    Seat: domain:spec#5 (seat post #19357)
    Clause-②: no (no schema or published-export change; the route and its closed parameter set are unchanged, as the ruling states)
    Scope: ruling A's execution parameters, taken whole. Level S.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 20896,
      "status": "done",
      "branch": "claude/issue-20896-template-import-door",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/20977",
      "session": "session_01Sfe5YjBLwB9J3y8fvm2xq1 (subagent run; the parent session's id)",
      "premise_still_valid": true,
      "summary": "Ruling A is in: on GET /data/:object/export, a request whose template value reads true (read by readTemplateMode on the template key alone) goes through the new enforceImportTemplateGates instead of the export gates. Those gates are the import door's own stage-1 call enforceApiAccess(..., 'import') (404/405), plus the caller's create permission, asked of the security service as explain({ object, operation: 'create' }). allowed false or a throw answers 403 PERMISSION_DENIED in the shared sendError envelope. No security service, or one without explain, passes, as enforceExportPermission does. Every non-template request goes through the export gates exactly as before. One dispatch assumption did not hold: the import door has no route-level check of the caller's create permission to reuse. Its route gates (stage 1 and the stage-2 writeMode gate) are object-level only. The caller's create is judged by the engine's security middleware on each written row (a PERMISSION_DENIED row inside a 200 report). So, following the ruling's intent, the template branch reuses stage 1 verbatim and asks the contract's non-optional explain for the middleware's verdict, with no re-derivation from permission sets; runtime mayReadRunState is the precedent. Fork clause NOT triggered: templateColumns takes no write mode, and getWritableFields(object, context) has no operation parameter; stage 2 is not asked because a template request names no mode. Text changes: docblocks at DATA_EXPORT_PARAMS and answerImportTemplate, docs/permissions/permission-sets.mdx, a new patch changeset, and one sentence corrected in the still-pending .changeset/18386-export-import-template.md, which this change made false. Clause-② no holds: the template has not been released yet (the 18386 changeset is still pending), so no published accept set narrows.",
      "tests": "All at head 501dca7347 (code blob rest-server.ts 8e09988a9310) unless noted; every heavy run through os-verify-lock, VERDICT lines quoted. (1) Build of the rest dependency closure: turbo build --filter='@objectstack/rest^...' --concurrency=2, 24/24 tasks, VERDICT command-exit 0, rebuilt after the main merge 86cb4bb146 (24/24, exit 0). (2) pnpm --filter @objectstack/rest typecheck: VERDICT command-exit 0 (tsc --noEmit plus check:test-typecheck OK, 0 debt). The test file is in tsconfig.test.json's program (tsc --listFilesOnly: 1 hit). (3) Full package suite, pnpm --filter @objectstack/rest exec vitest run --project local --maxWorkers=2: Test Files 248 passed (248), Tests 4962 passed, 114 skipped (5076), VERDICT command-exit 0. Earlier heads also green: 3c7d7dd4ef 245 files / 4891 passed; 86cb4bb146 248 / 4962. (4) import-template-route + rest-export-permission-gate + rest-server-closed-query-params + import-template: 4 files, 128 passed, exit 0. (5) Ablations, each via scripts/ablation-replace.mjs in wrap mode (anchor 1 -> 0, blob changed, then the restore proven: blob == HEAD 8e09988a9310 and git diff HEAD empty, plus an outer trap that compares hashes). The subject is imported as ./rest-server (src, relative), so no dist rebuild is involved. A1, the template branch put back behind the export gates (`if (false)`): 6 failed / 31 passed. Red: create+noExport 200, noCreate 403+builder never called, allowExport+noCreate 403, throw->403, create-only object serves, list-only object 405. Green: preservation. A2, caller create gate deleted: 4 failed / 33. Red: the 200 pin (via its explain-was-asked assertion), noCreate 403, allowExport+noCreate 403, throw->403. A3, every request routed through the import gates (`if (true)`): 2 failed / 35. Red: both preservation pins (no-allowExport export 403 EXPORT_NOT_PERMITTED with no row read; allowExport+noCreate export keeps pre-change headers/text/sha256 and never asks explain). A5, the object half judged by export exposure: 2 failed / 35. Red: both object-half pins. All four were also run once at 617255a015 with the same verdict counts, before the envelope fix. (6) node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack: exit 0, 93 commands for the 5 changed paths. All 93 were run at 501dca7347, each exit captured before any pipe. 89 exited 0 on the first pass. check:type-check-debt and check:skill-examples exited 3 PREREQUISITE NOT MET; after building their closure (turbo build of rest, runtime, driver-turso, plugin-auth, service-cluster, service-job, service-messaging and client-react: 35/35, exit 0) both re-ran to exit 0. check-empty-changeset --base origin/main exit 1: the DELIBERATE CORRECTION class (this PR edits the pending 18386 changeset); it stays red by design and needs a written confirmation on the PR. check:dual-build-cjs-loads exit 3: NOT MEASURED, reason: it reads dist of about 44 packages (apps, adapters, client, ...), which only a full build provides; CI builds them. Reconciliation dispatch-gates --ran with recorded exit codes: exit 0, 93 accounted, 92 run, 1 NOT-MEASURED. check:route-envelope first went red (siblingCode 59 vs 58) on the flat 403 body; the body now goes through sendError and the gate is exit 0. (7) Narrowed eslint: pnpm exec eslint --no-inline-config --format json on rest-server.ts + import-template-route.test.ts, exit 0, 2 files in the json, 0 errors, 0 warnings, at 501dca7347. Population from eslint.config.mjs: the files glob '**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}' (line 971) covers both, and .md/.mdx sit in no eslint glob. Invariance: the config never enables type-aware linting (its own text at :327-328: no parserOptions.project), and no export changed, so no untouched file's verdict can move. (8) PR CI at 501dca7347, read once with no waiting: all seven required contexts completed success; Check Changeset failure is the expected deliberate-correction red (not a required context).",
      "mcp_calls": "0",
      "api_writes": "3 relay writes, each one POST /repos/objectstack-ai/objectstack/dispatches executed by fleet-write.yml as objectstack-fleet[bot]: (1) pr_create, POST /repos/objectstack-ai/objectstack/pulls (draft), run 36793595529, read-back 6360 bytes identical; (2) label-write --assign os-justin, POST /repos/objectstack-ai/objectstack/issues/20977/assignees, run 36793656255, read-back matches; (3) this os-dev-report, POST /repos/objectstack-ai/objectstack/issues/20896/comments via post-stamped.mjs. An earlier pr_create attempt was refused by write-pace (exit 10, budget 40/h), so nothing was written and it does not count. git push: 5 pushes to the branch (empty-branch probe, 617255a015, 3c7d7dd4ef, merge 86cb4bb146, 501dca7347; not REST).",
      "open_questions": [
        {
          "question": "Check Changeset is red by design: this PR rewrites one sentence of the still-pending .changeset/18386-export-import-template.md. Old sentence: 'The same two permission checks as the export apply: an object that does not expose export answers 405, and a caller without the export permission answers 403.' New sentence: 'The import's permission checks apply, not the export's: an object that exposes neither create nor update answers 405, and a caller without the create permission on the object answers 403. The export permission (allowExport) is not needed.' check-empty-changeset requires the correction to be confirmed in writing on the PR. Confirm it?",
          "options": [
            "A: confirm on PR #20977 that the correction stays (it leaves Check Changeset red, which is not a required context, and the merge goes over it)",
            "B: revert the 18386 sentence and let .changeset/20896-template-import-door.md alone describe the gate; the next release then ships a minor entry stating the export gates beside a patch entry contradicting it"
          ],
          "recommendation": "A, because the 18386 note is unreleased and is the entry an upgrading reader will grep for the template; shipping it false and correcting it in a sibling entry of the same release is the erratum shape AGENTS.md refuses for CHANGELOG text."
        }
      ],
      "out_of_scope_findings": [
        "carrier: 承接者:无 · noted, not filed — the create verdict is composed from ISecurityService.explain because the contract has no dedicated create/write twin of canReadObject; explain denies a caller whose permission sets resolve EMPTY where the middleware skips its CRUD gate (closed direction, reachable only with no baseline set). Recorded in the PR's Acceptance notes and in the enforceImportTemplateGates docblock.",
        "carrier: seat (PR #20977 body) · noted, not filed — the body's 'Verification at opening' names head 3c7d7dd4ef; the head is now 501dca7347 (main merged as 86cb4bb146, then the refusal moved to the shared envelope). Suggested seat edit, one paragraph under Verification: 'At 501dca7347: the 403 answers { success: false, error: { code: PERMISSION_DENIED, message, details: { object } } } through sendError (check:route-envelope refused the flat form); rest typecheck exit 0; rest suite 248 files / 4962 passed exit 0; ablations A1-A3, A5 red as expected and restored; dispatch-gates 93 accounted, 92 run, 1 NOT MEASURED (dual-build-cjs-loads).'"
      ]
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling on report 5922602955 · 2026-10-01T01:04Z

    domain:spec seat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1), holder of claim 5921450654.

    • Verified against GitHub: PR fix(rest): the import template answers to the import door's gates, not the export's (#20896) #20977 is at head 501dca7347, the head the report names. It has 5 files (+241 / -32), is a draft, is assigned to os-justin, and says Closes #20896 followed by the claim's Clause-② line.
    • The premise the dispatch assumed did not hold, and the deviation is accepted pending review. The import door has no route-level check of the caller's create permission. Its stage-1 and writeMode gates are object-level, and create is judged per written row by the engine's middleware. So the template branch reuses stage 1 (enforceApiAccess(..., 'import')) verbatim and asks the contract's own explain({ object, operation: 'create' }) for the create verdict, with no re-derivation from permission sets. The at-tier review is asked to judge that the verdict matches ruling A's "the caller's create permission on the object". It is also asked about the noted divergence: explain denies a caller whose permission sets resolve empty where the middleware skips its CRUD gate, which is the closed direction.
    • Fork clause: not triggered. templateColumns takes no write mode.
    • Q1 (the correction to the still-pending .changeset/18386-export-import-template.md): the confirmation check-empty-changeset asks for is a person's (scripts/check-empty-changeset.mjs:605-612), not the seat's. After the review, the seat puts it to the maintainer on this PR with a decision comment and needs-user-decision, the same path as PR docs(changeset): correct two scope sentences in the pending service-analytics masked-field note #20991.
    • PR body: the seat adds the current-head verification paragraph the report drafted, in this act.
    • Next: needs:contract-review goes on the PR and this card, then the at-tier review. objectui#9600's pointer is posted at landing.

    Generated by Claude Code

  6. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 20896,
      "status": "done",
      "branch": "claude/issue-20896-template-import-door",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/20977",
      "session": "session_01Sfe5YjBLwB9J3y8fvm2xq1 (subagent run; the parent session's id)",
      "premise_still_valid": true,
      "summary": "Patch round after the maintainer chose B on decision 5922804275, per the seat's comment 5923146385 on PR #20977. New head 8e2d1fda64, one appended commit with no rebase, amend or force-push. It restores .changeset/18386-export-import-template.md from the merge base 525b8139a2. git diff of that file between the merge base and HEAD is empty (0 bytes), and the file's blob 542d0899944e equals both the merge base's and origin/main's. Everything else is unchanged: the template import-door change, its pins, the docs line and .changeset/20896-template-import-door.md. That changeset never referred to the 18386 correction (no mention of 18386, pending notes or corrections), so nothing was cut. main was not merged: no conflict, and the 12 commits since are CI's joint check on the merge ref. They touch other files of packages/rest (error-response.ts, tests, tsconfig.json), but not this diff's files. PR body untouched, as instructed.",
      "tests": "At 8e2d1fda64. node scripts/check-empty-changeset.mjs --base origin/main: exit 0 ('No changeset from the merge base modified or deleted by this diff'), and its --self-test exit 0. check-changeset-no-major --base origin/main: exit 0. check-adr-0087-registration --base origin/main: exit 0. pnpm --filter @objectstack/rest typecheck: VERDICT command-exit 0. Full rest suite (pnpm --filter @objectstack/rest exec vitest run --project local --maxWorkers=2): Test Files 248 passed (248), Tests 4962 passed, 114 skipped (5076), VERDICT command-exit 0. node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack: exit 0, 93 commands for 4 changed paths. It warns that the derivation tree is 12 commits behind origin/main, with 7 family files changed upstream. All 93 were run with exit codes captured before any pipe: 92 exit 0. check:type-check-debt and check:skill-examples first exited 3 (PREREQUISITE NOT MET in the recreated worktree) and exited 0 after their closure was built (35/35 cached). check:dual-build-cjs-loads exit 3: NOT MEASURED, because it needs the dist of about 44 packages; CI builds them. dispatch-gates --ran with exit codes: exit 0, 93 accounted, 92 run, 1 NOT-MEASURED. check:nul-bytes exit 0. The code is identical to 501dca7347, so the ablations reported on that head (A1-A3, A5) still apply unchanged.",
      "mcp_calls": "0",
      "api_writes": "1 relay write: this os-dev-report, POST /repos/objectstack-ai/objectstack/issues/20896/comments via post-stamped.mjs (relay dispatch POST /repos/objectstack-ai/objectstack/dispatches). git push: 1 (8e2d1fda64, not REST).",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  7. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR #20977 → 8f784959cf, and the card is done

    domain:spec seat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1) · 2026-10-01. Holder of claim 5921450654.

    • Landed: PR fix(rest): the import template answers to the import door's gates, not the export's (#20896) #20977 went through the merge queue as 8f784959cf, with one parent (bb2eccf7ed, read with git rev-list --parents). All 4 files have the same per-file git patch-id --stable as the reviewed head 8e2d1fda64 against the merge base 525b8139a2. Review records: 5922797800, then the delta PASS 5923454406.
    • Delivered (ruling A):
      • GET /data/:object/export?template=true is judged by the import door's own enforceApiAccess(..., 'import') plus the caller's create verdict from the security contract's explain.
      • The export gates no longer stand in front of it.
      • The non-template export is unchanged.
    • The maintainer's B on the 18386 note: .changeset/18386-export-import-template.md ships as written, beside this PR's patch entry.
    • Closed by Closes #20896 at merge. The seat now removes pm:dispatched and the assignee. The objectui#9600 pointer is posted in the same act.

    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions