Skip to content

feat: add optional visibility to metadata entries - #34

Merged
raymondk merged 1 commit into
dfinity:mainfrom
raymondk:feat/metadata-visibility
Jul 30, 2026
Merged

feat: add optional visibility to metadata entries#34
raymondk merged 1 commit into
dfinity:mainfrom
raymondk:feat/metadata-visibility

Conversation

@raymondk

Copy link
Copy Markdown
Collaborator

Exposes ic-wasm's metadata visibility to users, per metadata entry.

Today every recipe that takes a metadata parameter injects the sections with
ic-wasm … metadata "<name>" -d "<value>" --keep-name-section and never passes
-v, so user metadata always lands private with no way to change it — readable
only by a controller. The recipes clearly need the distinction themselves
(recipes/rust/recipe.hbs:33 passes -v public for candid:service); this makes
the same choice reachable from icp.yaml:

        metadata:
          - name: build:commit
            value: a1b2c3d
            visibility: public      # optional; private when omitted

The template change is one line per recipe, using the optional-parameter pattern
from .claude/CLAUDE.md:

-        - ic-wasm … metadata "{{ name }}" -d "{{ value }}" --keep-name-section
+        - ic-wasm … metadata "{{ name }}" -d "{{ value }}"{{#if visibility}} -v {{ visibility }}{{/if}} --keep-name-section

Backward compatible. Omitting visibility renders byte-for-byte the command
emitted before this change, so existing configurations build identically.

Scope

All five recipes that expose a user-facing metadata parameter: motoko, rust,
static-site, asset-canister, prebuilt. CONTRIBUTING asks for one fix per PR
and this is one change — but it lands in five files for consistency, since a
visibility that worked in only some recipes would be its own papercut. Happy to
split it per recipe if you'd rather review them separately.

Per .claude/CLAUDE.md's documentation-verification rules, each recipe also gets:
its {{! metadata: … }} doc-comment updated to describe the new field, its README
parameter-table row updated, and one README example extended so the option is
copy-pasteable. No version tags touched — releases are made via make release-recipe. icp-cli/docs/guides/using-recipes.md does not mention
metadata, so no cross-repo doc sync is needed.

Testing

Following the icp project showicp build procedure in .claude/CLAUDE.md,
with recipes referenced via type: file://… (icp-cli 1.2.0, ic-wasm 0.9.11).

Rendering, via icp project show — public, omitted, and a mixed list:

- ic-wasm … metadata "build:commit" -d "abc123" -v public --keep-name-section
- ic-wasm … metadata "build:commit" -d "abc123" --keep-name-section
- ic-wasm … metadata "pub:sect" -d "p" -v public --keep-name-section
- ic-wasm … metadata "priv:sect" -d "q" --keep-name-section

Note the omitted case renders correctly under icp-cli's handlebars strict mode.

Resulting sections after icp build, read back with ic-wasm <wasm> metadata:

Config Recipe Section
visibility: public prebuilt icp:public build:commit
omitted prebuilt icp:private build:commit
mixed list prebuilt icp:public pub:sect + icp:private priv:sect
visibility: public + omitted static-site icp:public build:commit + icp:private build:private

static-site is covered separately because it wraps the call in sh -c '…', a
different quoting shape from the bare command in motoko / rust / prebuilt.

Invalid values fail at build time with ic-wasm's own message, so no template-side
validation is needed:

ERR [bad] > error: invalid value 'bogus' for '--visibility <VISIBILITY>'
ERR [bad] >   [possible values: public, private]
Error: Canister(s) ["bad"] failed to build.

Motivation

We bake a service:git section (commit sha + repo origin) into all 33 canisters of
a suite so a deployed canister can be traced back to the commit that built it. The
natural consumer is a launcher frontend showing each app's deployed version, which
reads sections anonymously — invisible while the section is private. Details in #33.

Ref: #33

User-declared metadata sections were always injected without `-v`, so they landed
at ic-wasm's default visibility, private, with no way to change it. That makes them
readable only by a controller - so provenance, version strings and build info, the
things users typically want published, could not be read by a frontend or any other
non-controller caller.

The recipes themselves already need the distinction: the Rust recipe passes
`-v public` for its own `candid:service` section. This exposes the same choice to
users, per metadata entry:

    metadata:
      - name: build:commit
        value: a1b2c3d
        visibility: public

`visibility` is optional and follows the repo's optional-parameter pattern
(`{{#if visibility}}`), so omitting it renders exactly the command emitted before
this change - existing configurations are unaffected. Invalid values fail at build
time with ic-wasm's own error, which lists the possible values.

Applied to all five recipes that expose a user-facing `metadata` parameter
(motoko, rust, static-site, asset-canister, prebuilt), with the template
doc-comments and README parameter tables updated to match, and one example per
README extended so the option is copy-pasteable.

Ref: dfinity#33

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@raymondk
raymondk requested a review from a team as a code owner July 30, 2026 17:57
@cla-idx-bot

cla-idx-bot Bot commented Jul 30, 2026

Copy link
Copy Markdown

Dear @raymondk,

In order to potentially merge your code in this open-source repository and therefore proceed with your contribution, we need to have your approval on DFINITY's CLA.

If you decide to agree with it, please visit this issue and read the instructions there. Once you have signed it, re-trigger the workflow on this PR to see if your code can be merged.

— The DFINITY Foundation

@raymondk
raymondk merged commit 17b88c6 into dfinity:main Jul 30, 2026
9 of 10 checks passed
raymondk pushed a commit that referenced this pull request Jul 31, 2026
Publishes the `static-site` recipe at v0.3.2, pinning the canister and
sync-plugin wasm from dfinity/certified-assets's v0.3.2 release.

The committed `recipe.hbs` is the asset attached to that release,
verbatim — verify it matches:

https://github.com/dfinity/certified-assets/releases/download/v0.3.2/recipe.hbs

After merge, tag `static-site-v0.3.2` in this repo to cut the recipe
release.

------

### Context: version ordering

This publishes `static-site-v0.3.2`, below the existing
`static-site-v0.4.0`. That's
deliberate: the `static-site` recipe version tracks the certified-assets
release it
pins, and v0.4.0 pins v0.3.1 artifacts. A minor bump upstream also
carries a specific
meaning — breaking change, canister reinstall, every asset re-uploaded —
which doesn't
apply here.

Sequence: merge this → tag `static-site-v0.3.2` → retire the
`static-site-v0.4.0` tag
and release. One local checkout references it, coordinated directly.

#34's `visibility` option is unaffected: it was carried upstream in

[certified-assets#118](dfinity/certified-assets#118),
so it's in
the recipe committed here and the diff is only the two wasm pins. These
files are
regenerated from that repo on each publish, so changes persist by
landing there.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants