Auto-connect removable-media and three personal-files for coolcroco

Hi,

This is Ahmet, CoolCroco’s developer. The app has been in Microsoft Store for a while now and has <500 users.

`coolcroco` is a photo culling viewer for photographers: it reads a folder of RAW

files, holds the decoded frames in RAM so paging through a shoot is instant, and

files each frame into `Approved/` or `Rejected/` as you go.

Revision 1 is uploaded and currently held at

https://dashboard.snapcraft.io/snaps/coolcroco/revisions/1/review/ with:

human review required due to ‘allow-installation’ constraint (bool) declaration-snap-v2_plugs_installation (dot-config-mimeapps, personal-files)

human review required due to ‘allow-installation’ constraint (bool)

declaration-snap-v2_plugs_installation (dot-local-share-mime, personal-files)

human review required due to ‘allow-installation’ constraint (bool)

declaration-snap-v2_plugs_installation (dot-local-share-trash, personal-files)

It is strictly confined and I would like to keep it that way - classic confinement would be the wrong tool

here and I am not asking for it. Four connections do need to be automatic, because

in each case the failure mode is silent: the app looks broken or dishonest rather

than looking unpermitted.

### 1. `removable-media`

Photographers cull straight off the card. The normal first run is: insert an SD card

or plug in an external SSD, point the app at `/media/$USER/…`, and start rejecting

frames. With only `home`, that folder does not exist as far as the app can see - the

folder browser shows nothing and there is no error that could honestly explain why,

because the app cannot distinguish “empty” from “denied”.

This is the interface’s stated purpose and this is the archetypal case for it: a

media application whose input is, most of the time, physically removable media.

(Unlike the three `personal-files` requests below, `removable-media` isn’t holding

revision 1 in review - it doesn’t block installation. This request is only to spare

users the extra step of connecting it by hand.)

### 2. `personal-files: $HOME/.local/share/Trash`

Deleting a photo sends it to the freedesktop trash and the app then keeps a handle

on it so **Ctrl+Z restores it** (`src/recyclebin_linux.py`). Both halves are one

feature - an irreversible delete in a culling tool is a data-loss bug, not a reduced

feature set.

I looked at `org.freedesktop.portal.Trash` first and it does not fit: `TrashFile()`

takes a file descriptor and returns only a result code, so the app never learns where

the file went and cannot offer the undo. Writing the `.trashinfo` sidecar directly is

the only way to keep delete reversible.

Requested paths:

- `$HOME/.local/share/Trash` (write)

### 3. `personal-files: $HOME/.local/share/mime`

Eight RAW formats have no MIME type in any current `shared-mime-info` release -

Hasselblad `.3fr`/`.fff`, Phase One `.iiq`, Epson `.erf`, Mamiya `.mef`, Leaf `.mos`,

Samsung `.srw`, Panasonic `.rwl`. The snap ships a MIME package defining them under

the same names freedesktop uses, so the two merge cleanly once a release catches up.

snapd has no mechanism to install a MIME package system-wide, and the host’s

`shared-mime-info` does not read `$SNAP`. So the app copies the XML into the user’s

own MIME directory on first run and reruns `update-mime-database` there. Without

this, a Hasselblad or Phase One file has no type at all, which means the file

manager cannot offer to open it with anything - not just not with us.

Requested paths:

- `$HOME/.local/share/mime` (write)

### 4. `personal-files: $HOME/.config/*mimeapps.list`

The app has a “Make CoolCroco my default photo viewer” action, which writes the

default-application entries. It is deliberately conservative and already refuses to

touch a type the user has chosen by hand (`_chosen_by_hand()` in `src/assoc_linux.py`);

it claims only types nobody has explicitly assigned.

Three files because the app writes the plain list plus one per `$XDG_CURRENT_DESKTOP`

entry, which on Ubuntu (`ubuntu:GNOME`) is both of the others.

Requested paths:

- `$HOME/.config/mimeapps.list` (write)

- `$HOME/.config/gnome-mimeapps.list` (write)

- `$HOME/.config/ubuntu-mimeapps.list` (write)

### Why `home` does not cover 2–4

All three are hidden directories, which the `home` interface excludes by design. And

the app’s own `$HOME` is redirected into `~/snap/coolcroco`, so writing to

`$XDG_DATA_HOME` from inside the snap lands somewhere the desktop never reads -

these have to be real-home paths or they do nothing at all.

I am the sole publisher and upstream author, and the snap is built from the same

`build_app.py` freeze that produces the AppImage.

Thank you for your consideration :slight_smile:

This request has been added to the queue for review by the @reviewers team.

Hi @CoolCroco,

To make the review of your request easier, please use the following template to provide all the required details and also include any other information that may be relevant.


name: name of the snap
description: description of the snap
snapcraft: link to snapcraft.yaml if publicly available
upstream: link to the upstream repository if open-source or ‘PRIVATE’ otherwise
upstream-relation: relation of the snap publisher with the upstream
plugs:
  <interface-name>:
    interface: [optional] one of https://snapcraft.io/docs/reference/interfaces/
    attributes: [optional] interface attributes if any
    request-type: installation | manual-connection | auto-connection
    reasoning: why is this interface needed
  ...
slots:
  <interface-name>:
    interface: [optional] one of https://snapcraft.io/docs/reference/interfaces/
    attributes: [optional] interface attributes if any
    request-type: installation | manual-connection | auto-connection
    reasoning: why is this interface needed
  ...

where:

  • : the name of the interface as defined in the snapcraft.yaml .
  • interface: the interface being requested. Only required if different from interface-name
  • attributes: the interface attributes. Only required if attribute are defined in the snapcraft.yaml.
  • request-type: one of installation (ie. permission to upload the snap to the store using this interface), connection (ie. permission to allow the snap interface to be connected) or auto-connection (ie. permission for the snap interface to be automatically connected when the snap is installed).

Hi, thanks for the guidance. My request is edited below

name: coolcroco

description: A RAM-resident image viewer for fast photo culling. It decodes a whole

folder of photographs to display resolution on background workers and holds them

in RAM, so paging through a shoot in either direction is instant after the first

pass. Reads the major RAW formats via LibRaw plus HEIC/HEIF, JPEG, PNG, TIFF and

WebP, and files each frame into Approved/ or Rejected/ subfolders as the

photographer culls.

snapcraft: PRIVATE. The plugs are reproduced verbatim below; happy to post the whole

file, or any part of it, on request.

upstream: PRIVATE

upstream-relation: I am the sole author and copyright holder of the application and

the publisher of this snap. There is no third-party upstream.

plugs:

dot-local-share-trash:

interface: personal-files

attributes:

  write:

    - $HOME/.local/share/Trash

request-type: installation, auto-connection

reasoning: Deleting a photo sends it to the freedesktop trash, and the app keeps

  a handle on the trashed file so Ctrl+Z restores it. Those are one feature, not

  two: an irreversible delete in a culling tool is data loss, and a culling tool

  is used by making fast decisions you sometimes take back. I evaluated

  org.freedesktop.portal.Trash first and it does not fit - TrashFile() takes a

  file descriptor and returns only a result code, so the app never learns where

  the file went and cannot offer the undo. Writing the .trashinfo sidecar

  directly is the only way I found to keep delete reversible. Auto-connection is

  requested because an unconnected trash fails at the moment the user presses

  Delete, which is the worst time to discover a permission is missing; if you

  would rather grant installation only, I will detect the unconnected state and

  disable the delete action rather than let it fail.

dot-local-share-mime:

interface: personal-files

attributes:

  write:

    - $HOME/.local/share/mime

request-type: installation, auto-connection

reasoning: Eight RAW formats have no MIME type in any current shared-mime-info

  release - Hasselblad .3fr and .fff, Phase One .iiq, Epson .erf, Mamiya .mef,

  Leaf .mos, Samsung .srw, Panasonic .rwl. The snap ships a MIME package

  defining them under the same names freedesktop uses, so the two merge cleanly

  once a release catches up. snapd has no mechanism to install a MIME package

  system-wide and the host's shared-mime-info does not read $SNAP, so the app

  copies the XML into the user's own MIME directory on first run and reruns

  update-mime-database there. Without it those files have no type at all, which

  means the file manager cannot offer to open them with anything, not just not

  with us. Writes are confined to our own namespaced package file in that

  directory.

dot-config-mimeapps:

interface: personal-files

attributes:

  write:

    - $HOME/.config/mimeapps.list

    - $HOME/.config/gnome-mimeapps.list

    - $HOME/.config/ubuntu-mimeapps.list

request-type: installation, auto-connection

reasoning: The app has a "Make CoolCroco my default photo viewer" action. It is

  deliberately conservative and already refuses to touch any type the user has

  chosen by hand, claiming only types nobody has explicitly assigned. Three

  files because the app writes the plain list plus one per $XDG_CURRENT_DESKTOP

  entry, which on Ubuntu (ubuntu:GNOME) is both of the others. This is the one

  of the three I would most understand you declining to auto-connect, since it

  is a deliberate user action rather than something needed at startup:

  installation plus manual-connection would be workable here, and if even that

  is refused the button comes out and the app points at Settings -> Default

  Applications instead.

removable-media:

request-type: auto-connection

reasoning: Photographers cull straight off the card. The normal first run is:

  insert an SD card or plug in an external SSD, point the app at /media/$USER/...

  and start rejecting frames. With only home, that folder does not exist as far

  as the app can see, and there is no error it could honestly show, because it

  cannot distinguish "empty" from "denied". This is not blocking installation of

  revision 1; the request is only so that the archetypal first run works without

  the user first being sent to a terminal.

slots: none

Every other plug the snap uses (home, network, and the desktop/wayland/x11/opengl

set that comes with the gnome extension) is a base-declaration default and is not

part of this request.

Hi @CoolCroco,

Thank you.

Since the project is private and before I take a look at the technical justification, can you please confirm if coolcroco is a commercial product distributed by a company?

Hi @shishirsub10, thanks for your reply,

No, it is not. CoolCroco is not a commercial product and there is no company behind it.

I am an individual developer and the sole author, copyright holder and publisher. The app is distributed free of charge, with an optional donation link on my personal site. There is no paid tier, licence key, subscription or trial.

To be clear about one thing that may have prompted the question: license: Proprietary in the snap means closed-source, not commercial. The source repository is private, but nothing about the app is sold.

It is published the same way on the Microsoft Store, also free, under my own individual developer account rather than a company one: https://apps.microsoft.com/detail/9PJJ43VCF5F4

Hi @CoolCroco, thanks for confirming!

To ensure that the snap is published and maintained by a trusted entity in the Snap Store, we perform publisher vetting. Verified Accounts is the way to go for private publishers. As the snap is not associated with any institution, foundation or company, I am unable to proceed ahead with this request. Sorry for the inconvenience.