Skip to content

Add safe Installer Package inspection to swiftpkg and Swiftpkgr #31

Description

@jordancalhoun

Problem Statement

People can use swiftpkg and Swiftpkgr to create, import, edit, and build Apple Installer Packages from Package Projects, but they cannot directly examine an Installer Package before installing it. Package authors, administrators, and security reviewers need to understand package structure, payload destinations, Installer Scripts, Installation Choices and Requirements, signing provenance, notarization evidence, and embedded Payload Code without executing or installing untrusted content. Existing import support is not a substitute because inspection must be read-only, must support packages that cannot be imported, and must preserve multi-component distribution structure.

Solution

Add Package Inspection as a first-class workflow alongside Package Project authoring. A shared SwiftPkgCore inspection session will examine Installer Packages without installing payloads or executing scripts, then produce a versioned Inspection Report consumed by both the swiftpkg CLI and Swiftpkgr.

Full Inspection will be the default. It will describe package hierarchy, Payload Entries, Installer Scripts, raw and parsed metadata, Installation Choices and Requirements, Eligible Components on This Mac, package-container trust, and discovered Payload Code trust. Package-only Inspection will retain payload and script inventory while limiting trust checks to Installer Package nodes. Inspection will be offline by default; any Gatekeeper check that may contact Apple will require an explicit user action.

Swiftpkgr will provide independent multi-window Package Project and inspection sessions, searchable contents, non-launching previews, safe exports, explicit online verification, stale-source handling, and direct inspection of newly built packages. The CLI will expose equivalent capabilities through explicit options, stable human and JSON output, deterministic exit behavior, and automation-oriented policy checks.

User Stories

  1. As a package author, I want to inspect an Installer Package without importing it, so that I can review an artifact without creating a Package Project.
  2. As a Mac administrator, I want inspection to be read-only, so that examining a package never installs its payload.
  3. As a security reviewer, I want inspection never to execute Installer Scripts, so that reviewing untrusted packages does not run embedded code.
  4. As a CLI user, I want to invoke inspection explicitly with --inspect, so that package inspection is never inferred ambiguously from a path.
  5. As a Swiftpkgr user, I want to open .pkg files from Finder, so that I can inspect them through Open With without replacing Installer as the default application.
  6. As a Package Project author, I want to inspect a package immediately after building it, so that I can verify the delivered artifact without closing my project.
  7. As a Swiftpkgr user, I want Package Projects and Installer Packages in separate windows, so that inspecting an artifact does not discard unsaved project edits.
  8. As a Swiftpkgr user, I want each window to own independent state and operations, so that activity in one window does not replace or cancel another window's work.
  9. As a Package Project author, I want the app to reuse an existing project window for the same canonical URL, so that I cannot create conflicting edits or builds accidentally.
  10. As a package reviewer, I want flat Component Packages inspected, so that I can examine common modern packages.
  11. As a package reviewer, I want flat Distribution Packages inspected, so that I can understand their complete package hierarchy.
  12. As a package reviewer, I want multi-component distributions supported even when they cannot be imported, so that import limitations do not hide package structure.
  13. As a package reviewer, I want legacy Bundle Packages inspected, so that older enterprise packages remain reviewable.
  14. As a package reviewer, I want the report to distinguish Component Packages from Distribution Packages, so that their roles are clear.
  15. As a package reviewer, I want payload-free components distinguished from empty-payload components, so that zero files does not hide different receipt and script behavior.
  16. As a package reviewer, I want remote component references reported without automatic downloads, so that default inspection remains offline and predictable.
  17. As a package reviewer, I want embedded .pkg payload files listed without recursive inspection, so that nesting cannot trigger unbounded work unexpectedly.
  18. As a package reviewer, I want each package node's identity and metadata shown independently, so that outer distribution details do not conceal component details.
  19. As a package reviewer, I want every Payload Entry associated with its Component Package, so that content provenance remains clear.
  20. As a package reviewer, I want both archive paths and intended installed paths, so that I can relate package structure to filesystem effects.
  21. As a package reviewer, I want file type, size, ownership, permissions, and other declared metadata, so that I can understand how payload content is represented.
  22. As a package reviewer, I want directories and symbolic links represented accurately, so that the inventory is not limited to regular files.
  23. As a package reviewer, I want Payload Entries searchable by archive path, installed path, component identifier, and type, so that large packages remain navigable.
  24. As a CLI user, I want summarized human output by default, so that large payloads do not flood my terminal.
  25. As a CLI user, I want --list-entries, so that I can request the complete human-readable inventory.
  26. As a CLI user, I want repeatable case-insensitive substring filters, so that I can narrow large payload inventories without learning regex syntax.
  27. As a CLI user, I want an empty filter result to succeed, so that checking for the absence of a path is scriptable.
  28. As a package reviewer, I want Installer Scripts separate from Payload Entries, so that executed content is not confused with installed content.
  29. As a package reviewer, I want readable Installer Script source available, so that I can understand what may execute during installation.
  30. As a package reviewer, I want binary or undecodable scripts identified without guess-decoding, so that arbitrary bytes are not misrepresented as source text.
  31. As a CLI user, I want script names and metadata summarized by default and source shown with --show-scripts, so that normal output stays concise.
  32. As an automation author, I want readable script source included in JSON reports, so that tooling can analyze what may execute.
  33. As a package reviewer, I want parsed metadata alongside access to original raw resources, so that unknown fields are not silently discarded.
  34. As a package reviewer, I want Distribution Package Installation Choices preserved, so that conditional component selection is visible.
  35. As a package reviewer, I want declared Installation Requirements preserved, so that I can inspect the package author's conditions directly.
  36. As a package reviewer, I want Eligible Components on This Mac, so that I can see the applicable component route for my current system.
  37. As a package reviewer, I want current-host evaluations labeled with OS and architecture context, so that they are not mistaken for other Macs.
  38. As a package reviewer, I want the report to avoid simulating arbitrary target Macs, so that it does not claim certainty beyond the current host.
  39. As a package reviewer, I want Installer Script effects explicitly excluded from the eligible-component prediction, so that declarative results are not overclaimed.
  40. As a package reviewer, I want each package node's signature integrity reported, so that I can detect tampering.
  41. As a package reviewer, I want certificate trust reported separately from signature integrity, so that intact internally signed packages are described accurately.
  42. As a package reviewer, I want signing identity, Team ID, certificate purpose, chain, fingerprints, and validity dates, so that provenance is auditable.
  43. As a package reviewer, I want secure timestamp information and validity-at-signing-time distinguished from current certificate expiry, so that historical signatures are interpreted correctly.
  44. As a package reviewer, I want an untrusted certificate chain to fail the Trust Summary while retaining integrity evidence, so that the summary and details remain honest.
  45. As a package reviewer, I want stapled-ticket status reported independently, so that local notarization evidence is explicit.
  46. As a package reviewer, I want absence of a stapled ticket not to be labeled “not notarized,” so that online-only tickets are not misrepresented.
  47. As a package reviewer, I want optional Gatekeeper verification, so that I can request current Apple policy assessment deliberately.
  48. As a privacy-conscious user, I want online verification explicit through --verify-online or an app action, so that routine inspection never unexpectedly contacts Apple.
  49. As a package reviewer, I want online results labeled with host and tool context, so that policy-dependent evidence is reproducible.
  50. As a package reviewer, I want Passed, Failed, Absent, Unavailable, Not Performed, and Not Applicable trust states kept distinct, so that missing and failed evidence are not conflated.
  51. As a package reviewer, I want a Trust Summary for quick scanning, so that I do not need to parse every node when all applicable checks pass.
  52. As a security reviewer, I want the Trust Summary never to claim a package is safe, so that signing evidence is not confused with behavioral safety.
  53. As a package reviewer, I want Checks Failed, Attention Needed, Checks Passed, and Not Checked summary states, so that overall evidence is concise but nuanced.
  54. As a package reviewer, I want every underlying Trust Result retained beneath the summary, so that a roll-up never conceals evidence.
  55. As a package reviewer, I want trust results scoped to every Distribution Package, Component Package, and Payload Code object, so that an outer signature cannot hide an invalid child.
  56. As a package reviewer, I want Full Inspection to check discovered Payload Code by default, so that an outer package cannot receive Checks Passed while carrying invalid code.
  57. As a time-constrained user, I want --package-only, so that I can skip Payload Code trust checks while retaining payload and script inventory.
  58. As a package reviewer, I want the disclosed inspection scope beside every Trust Summary, so that Package-only Inspection cannot be mistaken for Full Inspection.
  59. As a package reviewer, I want Payload Code signing and notarization evidence independent from its containing package, so that nested trust is represented accurately.
  60. As a package reviewer, I want Payload Code entitlements and hardened-runtime status, so that objective execution capabilities are visible.
  61. As a package reviewer, I want Payload Code architectures and platform requirements, so that code compatibility is visible.
  62. As a package reviewer, I want application and bundle identifiers, names, versions, builds, and executable names, so that installed code is recognizable.
  63. As a package reviewer, I want nested signable code objects inspected independently, so that frameworks, helpers, and extensions do not inherit a parent's result.
  64. As a Swiftpkgr user, I want supported text, images, and structured data previewed in-app, so that I can inspect selected contents without exporting first.
  65. As a security-conscious user, I want previews never to launch executables or associated applications, so that inspection remains non-executing.
  66. As a package reviewer, I want unknown binaries and executable payloads to remain metadata/export-only, so that preview does not run untrusted code.
  67. As a user, I want to export a selected Payload Entry, Installer Script, or raw metadata resource, so that I can inspect it with external tools.
  68. As a CLI user, I want payload export selected by component identity and archive path, so that duplicate installed paths are unambiguous.
  69. As a CLI user, I want --export-entry, --export-script, and --export-metadata, so that each resource category remains explicit.
  70. As a CLI user, I want --component optional only for unique resources and --destination explicit, so that exports are predictable.
  71. As a CLI user, I want exactly one resource exported per invocation, so that overwrite and result semantics stay simple.
  72. As a user, I want recursive directory export, so that application bundles and other directory entries can be inspected intact.
  73. As a security-conscious user, I want archive traversal rejected and archived symlinks preserved without being followed, so that export cannot escape its destination.
  74. As a user, I want export never to overwrite by default, so that existing files are protected.
  75. As a CLI user, I want overwrite to require --overwrite, so that existing --force semantics are not overloaded.
  76. As a package reviewer, I want exports to preserve file content and safe structure without applying package ownership, ACLs, or extended attributes, so that export does not behave like installation.
  77. As a package reviewer, I want internal verification extraction to retain signature-relevant metadata, so that Payload Code verification remains accurate.
  78. As a Swiftpkgr user, I want temporary preview content scoped to the inspection window, so that it is removed when I close, cancel, or reinspect.
  79. As a CLI automation author, I want structured export results, so that exported type, selector, destination, size, and digest are machine-readable.
  80. As an automation author, I want --output-format json, so that inspection does not overload the existing --json Package Project flag.
  81. As an automation author, I want every JSON Inspection Report to contain an integer schema version, so that breaking contract changes are detectable.
  82. As an automation author, I want compatible additions not to change the schema version, so that consumers can tolerate evolution.
  83. As an automation author, I want deterministic JSON ordering, so that reports are meaningfully diffable.
  84. As an automation author, I want exactly one JSON document on stdout, so that progress messages never corrupt parsing.
  85. As an automation author, I want progress and diagnostics on stderr, so that machine-readable output remains clean.
  86. As an evidence reviewer, I want source digest, Swiftpkg version, inspection timestamp, scope, host context, and tool context, so that reports are traceable.
  87. As a privacy-conscious user, I want portable reports to omit absolute source paths, so that shared JSON does not leak usernames or internal shares.
  88. As a Swiftpkgr user, I want to export the same versioned JSON report as the CLI, so that both frontends produce interoperable evidence.
  89. As a Swiftpkgr user, I want a warning that exported reports may include readable scripts, so that sensitive embedded content is not shared accidentally.
  90. As a CLI user, I want report generation to exit successfully even when trust checks fail, so that findings remain data rather than operational errors.
  91. As a CI author, I want --require-checks-passed, so that I can make Failed, Attention Needed, or Not Checked summaries fail policy enforcement.
  92. As a CLI user, I want failures to preserve the existing exit code 255, so that inspection follows established CLI conventions.
  93. As a CLI user, I want cancellation to return 130, so that interruption is distinguishable from other failures.
  94. As an automation author, I want incomplete JSON reports emitted before a 255 exit, so that recoverable evidence remains available.
  95. As a package reviewer, I want partial reports when one package node is malformed, so that valid sibling information is not discarded.
  96. As a package reviewer, I want Inspection Issues scoped separately from Trust Results, so that parsing failures are not misreported as trust failures.
  97. As a package reviewer, I want unavailable online verification to remain a Trust Result rather than make the report incomplete, so that network failure is represented accurately.
  98. As a Swiftpkgr user, I want a report marked stale when its source package changes, so that old evidence is not presented as current.
  99. As a Swiftpkgr user, I want stale reports retained for reference but preview, export, and verification blocked until explicit reinspection, so that the source cannot change beneath an action.
  100. As a user, I want cancelled inspection to discard unfinished reports and temporary data, so that cancellation leaves no ambiguous evidence.
  101. As a security-conscious user, I want mandatory expansion, entry-count, nesting, and embedded-text limits, so that hostile packages cannot exhaust memory or disk.
  102. As a reviewer of large enterprise packages, I want bounded per-run limit increases, so that legitimate packages can still be inspected deliberately.
  103. As a CLI user, I want repeatable --inspection-limit name=value overrides, so that advanced limits do not require many permanent flags.
  104. As a Swiftpkgr user, I want limit overrides offered only after a limit issue and reset after reinspection, so that weakened limits do not become global defaults.
  105. As a privacy-conscious user, I want no persistent report or extraction cache, so that reopening a package always starts fresh.
  106. As a package reviewer, I want source and accessed-resource digests, so that inspected evidence can be identified precisely.
  107. As a reviewer of very large packages, I want per-entry payload digests calculated on demand, so that metadata-first inspection does not read every payload byte unnecessarily.
  108. As a product user, I want inspection capabilities released in the CLI and Swiftpkgr together, so that the two frontends remain consistent.
  109. As a maintainer, I want the CLI to retain macOS 13 support, so that adding the macOS 15 app workflow does not raise the CLI deployment target.
  110. As a maintainer, I want routine CI to avoid signing credentials and live notary calls, so that verification remains hermetic and reliable.

Implementation Decisions

  • SwiftPkgCore will expose one deep, session-oriented Package Inspection module. Its interface owns source fingerprinting, temporary extraction, report generation, on-demand resource access, export, online verification, cancellation, staleness, and cleanup.
  • The module's primary result is an immutable, Sendable Inspection Report. Both frontends consume the same report rather than maintaining separate package models.
  • Existing process execution and filesystem substitution seams will remain internal dependencies of the inspection module. Production uses Apple command-line tools; tests use the existing recording process adapter and temporary filesystem support.
  • Package Inspection is a peer workflow to Package Project authoring. Inspection never requires import or conversion.
  • Package Inspection never installs payloads, executes Installer Scripts, launches Payload Code, or opens inspected content in associated applications.
  • Full Inspection is the default scope. Package-only Inspection still inventories payload and scripts but omits Payload Code trust checks. Every report discloses its scope.
  • Default inspection is offline. --verify-online and an explicit Swiftpkgr action opt into Gatekeeper verification that may contact Apple.
  • Flat Packages, legacy Bundle Packages, Component Packages, and multi-component Distribution Packages are first-class inputs. Inspection does not inherit the importer's single-component distribution limitation.
  • Remote package references are reported but never fetched. Installer Packages embedded as payload files are listed but require explicit separate inspection.
  • Package hierarchy preserves per-node identity, metadata, contents, Installer Scripts, Installation Choices, Installation Requirements, and trust evidence.
  • Payload-free and empty-payload components remain distinct report states.
  • Payload Entries retain component identity, archive path, intended installed path, file type, size, ownership, permissions, and available declared metadata.
  • Intended installed paths are declarative. Reports warn that Installer Scripts can create or modify additional paths.
  • Distribution choices and requirements are preserved as authored. Evaluation occurs only for the current Mac and produces Eligible Components on This Mac with OS and architecture context.
  • Raw package metadata remains accessible alongside parsed values. Arbitrary raw resources are not embedded in the default report body; they use on-demand preview/export.
  • Readable Installer Script source is included in JSON Inspection Reports. Binary or undecodable scripts expose metadata and digest and remain export-only.
  • Trust Results use Passed, Failed, Absent, Unavailable, Not Performed, and Not Applicable.
  • Trust Summaries use Checks Failed, Attention Needed, Checks Passed, and Not Checked. Failed results fail the summary; Absent or Unavailable results require attention; skipped and inapplicable checks do not penalize the disclosed scope.
  • Trust Summaries are derived navigation aids. They never replace detailed results or claim an Installer Package is safe.
  • Signing Status separates signature integrity from host certificate trust and reports certificate purpose, identity, Team ID, full chain and fingerprints, certificate dates, secure timestamp, and validity at signing time.
  • An intact signature with an untrusted chain retains integrity evidence but fails the Trust Summary.
  • Notarization Status reports stapled-ticket evidence separately from requested Gatekeeper assessment. Absence of a stapled ticket never becomes a claim that the object was not notarized.
  • Host-derived trust results include macOS and tool-version context.
  • Full Inspection discovers signable Payload Code and reports signatures, notarization evidence, entitlements, hardened-runtime status, architectures, platform requirements, bundle identity, and nested code hierarchy.
  • Payload Code trust is independent of its containing Installer Package trust.
  • Inspection Reports include integer schemaVersion, Swiftpkg version, source filename and digest, inspection timestamp, scope, relevant host context, and tool context. Portable reports omit absolute source paths.
  • Compatible JSON additions retain the schema version. Structural removals, renames, or semantic changes increment it.
  • JSON ordering is deterministic except for provenance values that naturally vary. Semantic ordering such as certificate chains and Installation Choices is preserved; unordered collections use stable sorting.
  • With --output-format json, stdout contains exactly one valid JSON document and progress or diagnostics use stderr.
  • Human CLI output summarizes payload and script content by default. --list-entries expands payloads, repeatable --filter performs case-insensitive substring matching and implies listing, and --show-scripts prints readable source.
  • Zero CLI filter matches succeed. Missing or ambiguous export selectors fail with exit code 255 and identify candidate matches.
  • Payload Export resolves entries by Component Package identifier plus archive path; the component may be omitted only when the entry is unique.
  • CLI export uses --export-entry, --export-script, or --export-metadata, optional --component, required --destination, and explicit --overwrite. Exactly one resource is exported per invocation.
  • Export invocations render an export result instead of the full Inspection Report. --output-format json produces a separate versioned export-result document.
  • Directory Payload Export is recursive. Unsafe paths are rejected; symlinks are preserved but never followed during recursion.
  • User-facing exports preserve bytes, safe hierarchy, safe permission bits, and symlink targets but do not apply package-declared ownership, ACLs, or extended attributes.
  • Internal session extraction preserves metadata required for accurate code-signature verification and remains confined to an owner-only temporary directory.
  • Swiftpkgr previews supported text, image, and structured-data formats in-app. Executables, unknown binaries, and undecodable scripts remain metadata/export-only.
  • Swiftpkgr uses separate per-window Package Project and Package Inspection session models. Opening the same canonical Package Project focuses its existing window rather than creating conflicting sessions.
  • A successful build offers an explicit Inspect Built Package action in a separate inspection window.
  • Swiftpkgr registers as an alternate .pkg viewer for Open With but does not replace Installer as the default handler.
  • A source-package change marks an Inspection Report stale. The stale report remains visible, but preview, export, and new verification require explicit reinspection.
  • Cancellation discards the unfinished report and session temporary data. CLI cancellation returns 130.
  • Partial reports retain useful sibling results and scoped Inspection Issues. Incomplete CLI reports are emitted before returning 255.
  • Unavailable verification is a Trust Result, not an Inspection Issue. Default report generation succeeds when trust findings exist; --require-checks-passed returns 255 unless the summary is Checks Passed.
  • Every inspection enforces bounded archive expansion, entry count, nesting depth, and embedded-text limits. Limit violations produce Inspection Issues rather than silent truncation.
  • The CLI accepts repeatable bounded --inspection-limit name=value overrides. Swiftpkgr offers per-session increases only after a reported limit violation and never persists weakened defaults.
  • Reports and temporary extractions are session-scoped with no persistent cache. Reopening an Installer Package performs a fresh inspection.
  • Source packages and accessed resources receive SHA-256 digests. Arbitrary Payload Entry digests remain on demand to avoid reading all payload bytes.
  • The swiftpkg CLI retains macOS 13 support; Swiftpkgr retains macOS 15 support.
  • Frontend parity is a stable-release gate. Implementation may land incrementally, but the feature is not declared stable until both frontends expose the agreed shared capabilities.
  • Existing CLI flags, exit behavior outside inspection, Package Project layout, and build-info wire keys remain unchanged.

Testing Decisions

  • The highest test seam is the Package Inspection session interface. Tests assert observable reports, resources, exports, errors, cancellation, staleness, and cleanup through that interface rather than testing private parser or tool-wrapper state.
  • The existing recording process adapter and temporary-directory support provide hermetic Apple-tool and filesystem behavior. New internal seams are introduced only where at least production and test adapters genuinely vary.
  • CLI contracts are tested through the existing top-level CLI runner, covering option resolution, stdout/stderr separation, JSON validity, schema versions, exit codes, filtering, exports, policy enforcement, and cancellation.
  • Swiftpkgr tests focus on per-window session behavior, routing, stale-state gates, and action availability. Core report semantics remain covered at the shared session seam rather than duplicated in view tests.
  • The macOS integration loop dynamically builds representative unsigned packages and exercises end-to-end inspection through real Apple package tools.
  • Integration coverage includes flat components, scripts, payload-free components, empty-payload components, multiple build-info formats where relevant, distributions, multi-component distributions, and import-versus-inspection differences.
  • Unit fixtures capture representative signing, timestamp, certificate-chain, stapled-ticket, Gatekeeper, Payload Code, and malformed-tool outputs. Routine CI never requires Developer ID credentials, Keychain notary profiles, or live Apple service availability.
  • Trust tests cover every Trust Result state and Trust Summary aggregation, including mixed parent/child results, package-only scope, untrusted chains with intact signatures, expired-current certificates with valid timestamps, missing tickets, and unavailable online checks.
  • Safety tests cover absolute paths, .. traversal, symlink escape attempts, recursive directories, overwrite refusal, malformed archives, excessive nesting, entry-count limits, expansion limits, text limits, cancellation, and temporary cleanup.
  • Report tests verify deterministic ordering, required provenance, omission of absolute paths, stable schema semantics, partial-report validity, clean JSON stdout, and readable-script inclusion.
  • Payload Code tests cover nested code, entitlements, hardened runtime, architectures, minimum platforms, bundle identity, independent signatures, and Full versus Package-only Inspection.
  • Requirement tests preserve authored declarations and verify current-host evaluation context without attempting arbitrary target simulation.
  • Existing unit and macOS integration suites remain green throughout incremental delivery. The Swiftpkgr release configuration continues to build without code signing in CI.

Out of Scope

  • Installing packages, executing Installer Scripts, launching Payload Code, or replacing Installer as the default .pkg application.
  • Converting Package Inspection into Package Project import automatically.
  • Fetching remote component references.
  • Recursively inspecting Installer Packages found inside payloads.
  • Simulating arbitrary target Macs or predicting dynamic Installer Script behavior.
  • Heuristic “suspicious,” “safe,” malware, or behavioral risk scoring.
  • App Sandbox adoption; that requires a separate security and Apple-tool compatibility effort.
  • Persistent report, payload, preview, or extraction caches.
  • Opening exported JSON reports as standalone Swiftpkgr documents.
  • Signing or otherwise authenticating exported Inspection Reports.
  • Terminal preview of arbitrary payload bytes.
  • Eager payload-file previews or SHA-256 digests for every Payload Entry.
  • Automatic online verification.
  • Supporting inspection only in one frontend as a stable release.
  • Changing existing Package Project flags, layouts, build-info keys, or established non-inspection CLI exit behavior.
  • Recording an ADR during this specification session.

Further Notes

  • The project vocabulary is defined in the repository's root domain glossary. Package Project remains canonical because users migrating from munki-pkg already know that term; Package Workspace and Pkg Manager are intentionally avoided.
  • Package Inspection and Package Project authoring are peer workflows even though both use the same SwiftPkgCore engine.
  • Apple notarization tickets may be stapled to an artifact or available online, which is why local-ticket absence and explicit Gatekeeper assessment remain separate evidence.
  • The current unit suite and required macOS integration loop pass before implementation begins.
  • The existing SwiftPM app-icon warning is unrelated and tracked separately in issue Exclude Swiftpkgr app icon assets from SwiftPkgCore #30.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions