Skip to content

Configure app settings and permissions

Let an installer choose the objects and fields your app uses, and declare the permissions those choices require. Start with a scaffolded app and use a sandbox installation when testing permission changes.

The installation token is only half of API access. Every call the function makes as that token is checked against the scopes granted on the install. You declare what the app needs in requiredScopes. The installer can still uncheck items on the consent / install screen.

Write macros, not every leaf scope. Caraer expands them against the tenant catalog at install time (and again when settings change).

Macro Expands to
tools.forms.all Every tools.forms.* scope
records.candidate.all Record-level scopes for candidate (create / read / update / delete). Does not include property or relation scopes
records.candidate.properties_all Every records.candidate.property.* scope
records.candidate.relations_all Every records.candidate.relation.* scope
records.*.all Record-level scopes for every object. Use sparingly
global.all Every global.* scope

A typical “this app fully owns one object” pack is the three records.<object>.* macros together. The CLI wizard can add that pack in one step.

Concrete scopes (tools.apps.read) are fine when you need one permission only. tools.objects_schemas.write is the usual extra if install creates objects.

Do not hard-code records.candidate.all when the installer chooses the object. Put the setting name in angle brackets. Caraer substitutes the selected object when settings are saved:

settingsSchema:
- name: attendee_object
label: Attendee object
type: OBJECT_SINGLE_SELECT
required: true
- name: candidate_mapping
label: Candidate
type: MAPPING
required: true
requiredScopes:
- tools.objects_schemas.write
- records.<attendee_object>.all
- records.<attendee_object>.properties_all
- records.<attendee_object>.relations_all
- records.<candidate_mapping>.all
- records.<candidate_mapping>.properties_all
- records.<candidate_mapping>.relations_all

How substitution works:

  • <fieldName> must match a settingsSchema name.
  • OBJECT_SINGLE_SELECT / OBJECT_MULTI_SELECT use the selected object name (multi-select expands to one scope set per object).
  • MAPPING uses mappingValue.objectName, not the mapping items.
  • An empty or unset field grants no extra record scopes.
  • Changing the setting updates the install: scopes for the old object are removed, scopes for the new object are added.

The function still sees the setting value on body.settingsSchema. Use that value as the object name in API calls; the token is already scoped to it.

  • Settings are for admins installing the app, not for you. Keep required fields to the minimum that makes the app work.
  • Prefer SWITCH, OBJECT_SINGLE_SELECT, SINGLE_SELECT, and MAPPING over free-text object or property names.
  • Group related fields with settingsSections (or src/app/settings-sections/*.json). Caraer lays cards left-to-right, max three across. Unassigned fields land in Other settings.
  • Hide advanced fields behind a switch:
- name: custom_mapping
type: SWITCH
defaultValue: false
- name: field_mapping
type: MAPPING
visibleWhen:
- field: custom_mapping
operator: EQUALS
value: true

Hidden fields are not required and their values are dropped.

  • valueScope: USER stores the value per Caraer user (calendar picks). Default is COMPANY (one value for the install).
  • FILE / MULTI_FILE belong on app-bar action dialogs, not as everyday install settings.
  • Return quickly from webhooks and inbound handlers. Enqueue POST {caraerApiBase}/v2/apps/{appUuid}/installation/jobs for work that can exceed the 60s function timeout.
  • Set waitUntilComplete: true on lifecycle/install.json (and update.json if settings save must show hook-written mappings) so the install request waits for the function.
  • Put shared helpers in src/app/shared/ and import require("../../shared") from a function folder. Do not copy files.
  • Read third-party tokens from body.secrets / body.connections. Root .env is for your deploy-time keys (GOOGLE_CLIENT_SECRET), not installer secrets. See External OAuth and secrets.