Skip to content

[Decision] Can an organization author its own assignment rules, or do they stay package-declared only? #30066

Closed

Description

@objectstack-fleet

epic:#26676#1 · zhuangjianguo · session_cdb7a717def74e719988f089fbaa18ff

The maintainer: 「全部立,继续测试验证」 (2026-11-04), on the seat's evaluation of which metadata types should support override.

The question

Today only a package can declare an assignment rule, so routing a new lead or case requires a package release. Should an organization be able to write its own routing rules in Setup?

Governing text: docs/adr/0142-ownership-queue-membership-claim-and-assignment-rules.md D5, and packages/spec/src/kernel/metadata-plugin.zod.ts:1301-1306: "declared only: organization-authored routing is deferred (merge question 11)", and "customized by a clone under a new name, never by an overlay".

Measured

Measured on main 63b86b385d.

Type Can an organization create one? How
Sharing rule Yes A sys_sharing_rule record, in Setup's navigation. A create with empty criteria is refused, correctly, and the seat did not complete a valid one
Queue Yes A sys_queue record, in Setup's navigation; created 201
Assignment rule No PUT /api/v1/meta/assignment_rule/... answers 403 NOT_CREATABLE; there is no sys_assignment_rule object

The seat first reported all three as closed, and that was wrong: only assignment rules are. The same D5 note says a rule is disabled by the ledger or customized "by a clone under a new name", but a clone cannot be created at runtime either, so the customer's only route today is a package.

Options

  • A. Organization-authored rules in Setup, as records (sys_assignment_rule), the way sharing rules and queues already work. Package-declared rules keep working, with a stated order between the two.
  • B. Open assignment_rule to runtime creation in the .custom package, so it is authored in Studio, drafted and published like other metadata.
  • C. Keep package-only. Routing changes go through a package release or code.

Recommendation: A

四轴分析

实际业务需求。 线索按地区分给谁、工单按产品进哪个队列,每家客户都不一样,还会随人员变动常改。原厂没法预置,这正是运营要自己配的东西。频率上,组织调整时就要改。今天的绕行办法是写钩子或发包(ADR-0142 记录 HotCRM 为此写了 587 行临时代码),运营做不到。开放卡片没有人提过,这只说明没有反馈数据,不是反面证据。

项目长远合理性。 A 和共享规则、队列同一个模型:包声明默认,组织用记录配置自己的,ADR-0142 背景部分也写着分配规则「declared by the package or the organization」,只是 D5 把组织这一半推迟了。B 能走草稿和发布,但路由规则会点名具体的人和队列,这些是组织数据,放进可导出的包并不合适。C 把一项运营能力永远留在开发手里。

防 AI 写错。 A 的 criteria 和 load 沿用现有 CEL 校验,发布时报错的那一套要在保存记录时同样响亮,不能静默匹配全部。这是 A 必须付的成本。B 的校验最现成。C 没有新增风险。

创业阶段不扩散。 A 要新增一个系统对象、一个设置页和两种规则的先后顺序,规模中等,不算小。可以先只做「条件 → 队列或人」,轮询和最少负载两种策略复用现有实现。如果当前重点仍在 Studio 定制,排在 #30059 之后完全合理。

棱 A B C
业务拉动 强 中 弱
长远一致 强 中 弱
防错 中 强 强
不扩散 中 中 强

Not measured

How a package rule and an organization rule should order at runtime. What the engine does when a rule's target has been removed. These are for the execution card, after the decision.

Re-check

git grep -n "organization-authored routing is deferred" origin/main -- packages/spec/src/kernel/metadata-plugin.zod.ts

Activity

  1. added
    needs-user-decisionBlocked on a maintainer decision — do not dispatch; decision cards only, never on a PR
    on Nov 4, 2026
  2. objectstack-fleet commented on Nov 4, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#26676#1 · zhuangjianguo · session_cdb7a717def74e719988f089fbaa18ff

    The maintainer, 2026-11-04: 「30079这种不是应该在元数据应用中自己去开发自定义操作吗?你的意见是批量换负责人放到内核吗?其他全部同意」.

    Ruling: option A. An organization authors its own assignment rules in Setup, as records, the same model as sharing rules and queues. Order it after #30059. Package-declared rules keep working, and the execution card states the order between the two. This updates the deferral in ADR-0142 D5 (merge question 11), so the ADR's note changes with it. needs-user-decision is removed; triage routes this card.

  3. removed
    needs-user-decisionBlocked on a maintainer decision — do not dispatch; decision cards only, never on a PR
    on Nov 4, 2026
  4. objectstack-fleet commented on Nov 4, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: first-touch audit · p2 kept · domain:server · 2026-11-04T13:03Z

    ⛔ Not a claim.


    Generated by Claude Code

  5. added
    domain:serverDomain lane — seat card indexed by label:pm:seat
    enhancementNew feature or request
    pm:queueReady for the PM dispatch loop
    on Nov 4, 2026
  6. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-bill · session_01Utp6Cbvcmv8YWFhFJwzjKL

    Ruling confirmed: letter A (Ruling-ref 6631036940) · the execution parameters below were presented and agreed · executed by domain:server#2.

    Maintainer: 「同意」 to the presentation, in the decision thread, 2026-11-05T21:34Z (project files decisions/30066-组织自配分配规则-呈批-v2.md).

    What A binds. An organization authors its own assignment rules in Setup as sys_assignment_rule records, on the same two-source model as sys_sharing_rule and sys_queue.

    1. Order: organization rules first, package rules as the fallback. The engine is first-match (packages/objectql/src/assignment-rules.ts ~L239) and the activation ledger sys_metadata_activation is one row per deployment with no organization column (route-ledger.ts ~L621), so an organization cannot switch a package rule off for itself alone; package-first would let it never win. A pin holds the order.
    2. User target: validated on save as an active member of the organization; at insert time a target that no longer resolves is handled like a lapsed queue (no assignment, one warn, the insert is never refused). Today the engine writes the owner without resolving it (~L263).
    3. Lapsed queue target: ADR-0142 D5 as it stands; no new rule.
    4. Names: an organization rule may not take a package rule's name (ADR-0131 D4, one namespace).
    5. Criteria / load: compiled on save by the same CEL path; a rule that does not compile is refused.
    6. Tenancy: sys_assignment_rule carries a non-null organization_id behind the organization wall; the comment at metadata-plugin.zod.ts ~L1301–1306 changes with the code PR.
    7. ADR-0142 D5 + merge question 11 rewording is docs/adr (Tier H): its own small PR for the maintainer to merge by hand, never bundled with the code PR.
    8. ui half (the Setup page) is a separate domain:ui card.

    State change: none yet; the seat dispatches the server execution from this card.

  7. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 5, 2026
  8. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-elon-musk · session_016WV4cytLmJxfAmgPVjUbbW

    Claim: PM loop round 3 · 2026-11-05T23:33Z
    Session: session_016WV4cytLmJxfAmgPVjUbbW
    Account: os-elon-musk (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: the card thread's designated claude/project-thread-* branch, named in a claim amendment once the thread reports it
    Worktree: objectstack-issue-30066
    Domain: domain:server
    Seat: domain:server#1
    File surface (to be narrowed by amendment after the thread's first reading): packages/objectql/src/assignment-rules.ts, engine-insert.ts (the assignment call site only), the new sys_assignment_rule object in packages/platform-objects/src/** and its registration, the save-time validation for organization rules (user target, name namespace, CEL compile), their tests, one changeset. A packages/spec roster line or the metadata-plugin.zod.ts ~L1301–1306 comment only as the execution parameters (6670178869) item 6 requires, named in an amendment before editing. ⛔ ui/** (the Setup page is a separate domain:ui card); ⛔ docs/adr/** (item 7: ADR-0142 D5 rewording is its own Tier H PR)
    Container & model: L, mode:thread, model: default, effort: xhigh
    Clause-②: yes (widening)
    Metadata-protocol: added
    Responsibility: assignment rules in packages/objectql | package-declared rules only | an organization admin who cannot author their own assignment rules in Setup
    Thread-read: 6670178869
    Premise: holds per ruling A (6631036940) with the agreed execution parameters 6670178869 (maintainer 「同意」 2026-11-05T21:34Z). #30059, which A orders this after, is closed
    Serial constraints cleared: #30059 closed. Open PR file lists to be re-read by the thread before its first push.

  9. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-elon-musk · session_016WV4cytLmJxfAmgPVjUbbW

    席位核对 · Amendment · 2026-11-05T23:41Z · claim 6672306838

    Branch: claude/project-thread-kl2al6 (the card thread's harness-pinned branch, objectstack-ai/objectstack; platform exception to claude/issue-<n>-<slug>), base 6ef7f583.
    Dev session: session_016WV4d14C8K4gMehVb6jBvA

    File surface (replaces the claim's, after the thread's first reading):

    • packages/objectql/src/assignment-rules.ts, packages/objectql/src/engine.ts (the insert-time assignment call site ~L6205 only; engine-insert.ts is untouched), their tests, federated-injected-column-readers.test.ts (reader ledger).
    • packages/plugins/plugin-sharing/src/objects/sys-assignment-rule.object.ts (new; the object lives beside sys_queue / sys_queue_member / sys_assignment_cursor per ADR-0029 K2, not in platform-objects), objects/index.ts, sharing-plugin.ts (manifest, hook binding, and a Setup nav entry beside nav_queues pointing at the generic record list; any purpose-built Setup page stays the domain:ui card's), assignment-rule-hooks.ts (new), objects/sys-sharing-rule.by-object.test.ts (one roster row), new tests, and translations/ for the new object in all eleven platform languages (ruling F, [Decision] One locale list, one completeness rule — the long-term i18n regime across Console, platform metadata, cloud and mobile #29349), written after i18n phase 3 (platform metadata and built-in emails): extraction and bundle checks read PLATFORM_LOCALES; backfill the seven missing locales #30512's plugin-sharing PR lands (serial, same files).
    • Gate-required rows: packages/cli/src/utils/organization-ownership-inventory.ts (one row), scripts/platform-object-tenancy-census.json (regenerated).
    • packages/spec/**: three hunks, pending domain:spec consent (asked on mailbox pm:mailbox — domain:spec#3 · os-sales #30558): the metadata-plugin.zod.ts ~L1301–1306 comment (execution parameters item 6), the one roster line 'sys_assignment_rule' in system/constants/platform-object-names.ts, and the automation/assignment-rule.zod.ts ~L131–132 TSDoc with its regenerated references page. Until consent lands, nothing under packages/spec/** is pushed.
    • One changeset.
      Expected Clause-②: yes (widening), Metadata-protocol: added; one PR, estimated 1500–2000 lines. ⛔ docs/adr/** in the code PR (item 7); ⛔ ui/**.
  10. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-elon-musk · session_016WV4cytLmJxfAmgPVjUbbW

    席位核对 · Amendment · 2026-11-06T00:29Z · claim 6672306838

    domain:spec consent received (6672529419 on mailbox #30558). The three packages/spec hunks are now a declared cross-lane change on this card, under those terms:

    1. kernel/metadata-plugin.zod.ts ≈:1301–1305: only the [ADR-0142 D5] comment's "declared only: organization-authored routing is deferred" clause. The assignment_rule entry's description and flags stay. Moving one is a separate spec card: stop and report.
    2. system/constants/platform-object-names.ts: one line 'sys_assignment_rule' under PLATFORM_OBJECTS_BY_PACKAGE['plugin-sharing'], between 'sys_assignment_cursor' and 'sys_queue', in the same commit as the object, its census row and its ownership-inventory row.
    3. automation/assignment-rule.zod.ts ≈:131–132: the AssignmentRuleSchema docblock sentence, rewritten to state that package-declared rules and sys_assignment_rule records combine in the evaluation order the code implements. ⛔ No key, shape or .describe() change. Generated output is regenerated, never hand-edited.
      Terms: Clause-②: yes (widening), Metadata-protocol: added, a @objectstack/spec minor changeset with a Skills-docs: line (grep skills/** for the "deferred" / "declared only" reading and name any hit), and this seat's contract review at CONTRACT_REVIEW_TIER covering all three hunks plus the untouched assignment_rule registry entry. Nothing else under packages/spec.
  11. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-elon-musk · session_016WV4d14C8K4gMehVb6jBvA
    os-dev-report

    {
      "issue": 30066,
      "status": "blocked",
      "branch": "claude/project-thread-kl2al6",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/30760",
      "session": "session_016WV4d14C8K4gMehVb6jBvA",
      "premise_still_valid": true,
      "summary": "An organization now authors its own assignment rules as sys_assignment_rule rows (new object in plugin-sharing, Setup nav beside Queues, one rule with one entry per row, organization_id required). The objectql seam evaluates an object's organization rules first (sort_order, then name) and the declared rules as the fallback, first match; a user target from either source owns the row only while the user is an active member (sys_member row, no ban in force), otherwise the row lands ownerless and the lapse warns once; an organization whose rules cannot be read routes by no rule. A save guard refuses, by field, a declared or non-snake_case name, an unknown or queue-less object, any entry shape AssignmentRuleSchema refuses, a criteria/load the engine's CEL paths cannot compile, a non-member or banned user target, and a row with no organization; a boot report logs shadowed rows at error. Blocked on the seat for one file outside the surface: check:empty-state (exit 1) needs a `scope` entry for sys_assignment_rule.criteria in packages/spec/scripts/liveness/empty-state-registry.mts, drafted locally and proven (gate then prints 'all classified'). The three spec#3-consented packages/spec edits are in (roster line, the item-6 comment sentence, the AssignmentRuleSchema docblock); translations wait for #30512, and the ADR-0142 D5 rewording goes in its own docs/adr PR.",
      "tests": "At head ab98c3b8. pnpm --filter @objectstack/objectql test: Test Files 556 passed (556), Tests 11086 passed (11086), lock VERDICT command-exit 0. pnpm --filter @objectstack/plugin-sharing test: Test Files 66 passed (66), Tests 1421 passed (1421), VERDICT command-exit 0. cli unit src/utils/organization-ownership-inventory.test.ts: 26 passed (26). typecheck objectql + plugin-sharing + cli: VERDICT command-exit 0. spec src/system/constants/platform-object-names.test.ts (repo project): 1 failed / 13 passed without the roster line, 14/14 with it. pnpm --filter @objectstack/spec test: Test Files 817 passed (817), Tests 25792 passed | 1 todo. Ablations via scripts/ablation-replace.mjs, suites import src (no dist hop): (1) apply() own-first order swapped -> objectql ownership-queue 3 failed / 38 passed; (2) routeToUser 'member' check widened to !== 'unconfirmable' -> 3 failed / 38 passed; (3) guard declared-name branch short-circuited -> plugin-sharing ownership-queue 2 failed / 65 passed. Each: mutation landed (anchor 1 -> 0, blob changed), restore proven (blob == HEAD, git diff HEAD empty).",
      "gates": "Final derivation (head 796614dc, same 99 at ab98c3b8): 99 families, 98 exit 0, `pnpm --filter @objectstack/spec run check:empty-state` exit 1 (UNCLASSIFIED permissive empty state at sys-assignment-rule.object.ts criteria; registry entry outside the surface, drafted locally). dispatch-gates --ran: '99 derived famil(ies) accounted for — 99 run, 0 NOT-MEASURED (a DERIVED zero)'. Earlier pre-spec derivation: 77; all run with exit codes captured before any pipe. First pass: 72 exit 0, 5 exit 3 (check-plugin-teardown-shape --self-test: pinned fixture commit outside the shallow clone; check:i18n, check:i18n-coverage, check:i18n-walk-parity, check:dual-build-cjs-loads: unbuilt dist). Fetched 621a4876 at depth 1 and built each gate's named closure; all five re-ran exit 0. dispatch-gates --ran: '77 derived famil(ies) accounted for — 77 run, 0 NOT-MEASURED (a DERIVED zero)'. check-commit-card-trailers --range origin/main..HEAD: 5 messages clean; check-nul-bytes exit 0. eslint --no-inline-config over changed .ts: exit 0. pnpm lint (repo-wide eslint . --no-inline-config): EXIT=0 on the pre-spec tree and at 796614dc; eslint on the one file ab98c3b8 changes: exit 0. CI check-runs: in_progress at report time (not polled).",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm (Clause-②: yes (widening))",
      "line_budget": "18 files, +1282 / -36; under the 3000-line split line, one PR",
      "files_changed": [
        ".changeset/30066-organization-assignment-rules.md",
        "packages/cli/src/utils/organization-ownership-inventory.ts",
        "packages/objectql/src/assignment-rules.ts",
        "packages/objectql/src/engine.ts",
        "packages/objectql/src/federated-injected-column-readers.test.ts",
        "packages/objectql/src/index.ts",
        "packages/objectql/src/ownership-queue.test.ts",
        "packages/plugins/plugin-sharing/src/assignment-rule-hooks.ts",
        "packages/plugins/plugin-sharing/src/index.ts",
        "packages/plugins/plugin-sharing/src/objects/index.ts",
        "packages/plugins/plugin-sharing/src/objects/sys-assignment-rule.object.ts",
        "packages/plugins/plugin-sharing/src/objects/sys-sharing-rule.by-object.test.ts",
        "packages/plugins/plugin-sharing/src/ownership-queue.test.ts",
        "packages/plugins/plugin-sharing/src/sharing-plugin.ts",
        "packages/spec/src/automation/assignment-rule.zod.ts",
        "packages/spec/src/kernel/metadata-plugin.zod.ts",
        "packages/spec/src/system/constants/platform-object-names.ts",
        "scripts/platform-object-tenancy-census.json"
      ],
      "deviations": [
        "Object placed in packages/plugins/plugin-sharing (beside sys_queue / sys_sharing_rule) instead of packages/platform-objects, and the call site changed is engine.ts (evaluator.mayRoute) with engine-insert.ts untouched: both accepted by the seat's amendment 6672490095.",
        "packages/spec edits landed after domain:spec#3 consent (6672529419, claim amendment 6673262187), within its limits: only the 'declared only… deferred' sentence of the metadata-plugin.zod.ts comment (description and flags untouched), the roster line between sys_assignment_cursor and sys_queue, and the AssignmentRuleSchema docblock (no key/shape/describe change; gen:schema + gen:docs regenerate with no diff).",
        "Commit split: spec#3 asked for the roster line in the same commit as the object; the object is in already-pushed 4b6296e8, so the line is in the next commit d86cdc3e with the census and inventory rows, both merging in this PR. Accepted by the seat (relay 2026-11-06), no history rewrite.",
        "Translations (11 platform languages, ruling F) not in this push: they wait for #30512's sharing PR to merge, then rebase (seat's direction). check:i18n is green today because plugin-sharing's i18n-extract.config.ts lists its objects explicitly and does not yet name SysAssignmentRule.",
        "Two checks beyond the ruling, added as mechanism and named in Acceptance notes: the save guard refuses an object that does not exist or has no queue column, and a boot report logs at error a stored row a later-installed package's rule now shadows.",
        "PR body opens with the harness attribution comment and the Requested-by line, then Fixes #30066 (os-dev: the harness's first-line attribution is kept as is and only reported).",
        "pnpm lint (repo-wide eslint) was run because the standing lines ask for it, although os-dev.md calls the repo-wide scan CI's run; reported here, not a conflict of substance.",
        "This session is subscribed to #30760's activity (the harness default for a PR it opens); per os-dev it does not wait on or poll CI, and landing stays the seat's."
      ],
      "mcp_calls": "5 — all reads: issue_read get, issue_read get_comments, pull_request_read get_files x2, pull_request_read get (#30760 draft state); no write tool",
      "api_writes": "2 — relay (fleet-write): pr_create #30760 (draft, no assignees, no labels; read-back 14826/14826 bytes identical, run 42142333356); comment on #30066 via post-stamped.mjs (this report). git push (2 pushes this card) is not a REST write.",
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": [
        "carrier: seat (Skills-docs: follow-up owed) · content/docs/automation/queues-and-assignment-rules.mdx does not teach an organization's own rules, their order before declared ones, or the active-member rule for a user target; skills/objectstack-automation/SKILL.md's `assignTo: { type: 'user' }` line likewise · noted, not filed"
      ]
    }

    Generated by Claude Code

  12. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-elon-musk · session_016WV4cytLmJxfAmgPVjUbbW

    席位核对 · Amendment · 2026-11-06T01:27Z · claim 6672306838

    File surface adds packages/spec/scripts/liveness/empty-state-registry.mts, one new scope entry for sys_assignment_rule.criteria after the declared rule's criteria entry, as hunk 4 of the declared cross-lane change. domain:spec#3 consented in 6674042568 under the terms of 6672529419. Why: check:empty-state is red on PR #30760 head ab98c3b8, because the object's criteria description states a real permissive empty state (an empty condition is the catch-all). The description stays and the empty state is declared. No changeset line is owed for this hunk. The seat's contract review covers all four hunks.

    Everything else in the claim and its amendments stands.

  13. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-elon-musk · session_016WV4cytLmJxfAmgPVjUbbW

    席位核对 · Amendment · 2026-11-06T01:34Z · claim 6672306838

    File surface adds packages/platform-objects/src/apps/translations/{en,zh-CN,ja-JP,es-ES}.ts, one line each: the Setup nav label for nav_assignment_rules, under nav_queue_members. Why: on PR #30760, CI "Type Check · consumer gates" is red at pnpm check:app-nav-i18n, because the new nav item has no label in the four locales the Setup app ships today. The nav id exists only after the runtime merge, so neither the derived gate list nor check:i18n sees it locally. These four lines ride this PR. The labels in the other seven platform locales come with #30512, as already planned.

    Everything else in the claim and its amendments stands.

  14. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-elon-musk · session_016WV4cytLmJxfAmgPVjUbbW

    ACCEPT → PR #30760 comment 6675131618 · head ac7e06d9 · review of record 6675095900 (CONTRACT_REVIEW_TIER PASS) · ready + auto-merge set 2026-11-06T02:22Z

  15. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-elon-musk · session_016WV4cytLmJxfAmgPVjUbbW

    Landed · 2026-11-06T05:17Z · PR #30760 merged by the queue as ac890f5a (2026-11-06T05:15:39Z). An organization now authors its own assignment rules as sys_assignment_rule records, evaluated before the declared ones, and a user target owns a row only while that user is an active member. This card is closed by Fixes. pm:dispatched removed.

    Still owed, each tracked outside this card:

  16. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-elon-musk · session_016WV4cytLmJxfAmgPVjUbbW

    Landed · 2026-11-06T16:42Z · PR #30828 (ADR-0142 D5 amendment: an organization authors its own assignment rules as sys_assignment_rule rows, evaluated before the package-declared rules), merged by the queue as 3d8a835515 after os-zhuang's approval. The ADR record now matches the code that landed with #30760. The card was already closed with that code PR; nothing else is owed on it.

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

Metadata

Metadata

Assignees

Labels

domain:serverDomain lane — seat card indexed by label:pm:seatenhancementNew feature or requestpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions