[Feature Request] Optional items whose resolver cannot authenticate resolve to undefined, and lazy plugin functions in untaken branches

Open
#1,147 3 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
35/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Quiet
Tech stack
typescript
Domain
backend, security

Research direction

Start by reading the resolver evaluation and plugin function lookup entry points, then trace how optional items handle resolver errors and how if() evaluates its branches. The issue gives reproductions on 1.21.0 but names no files or tests; identify the relevant tests and use both examples to check completion: optional authentication failures warn and resolve to undefined when opted in, and an unloaded plugin function in an untaken branch does not error.

Written by the indexing model from the issue text.

Description

Description

Let an @optional item whose resolver cannot run come out as undefined (with a warning) instead of failing the whole load, as an opt-in. And let a plugin function that is not loaded sit in a branch that never runs.

Motivation

In a public repository, contributors and CI jobs have no access to the maintainers' 1Password, but the maintainers want signing credentials to come from it. Two things stand in the way, both reproduced on 1.21.0:

  1. An @optional item whose value is op() fails the load when there is no token and no app:
# @plugin(@varlock/1password-plugin)
# @initOp(token=$OP_TOKEN, allowAppAuth=false, useCliWithServiceAccount=true)
# @defaultSensitive=false
# ---
# @type=opServiceAccountToken @internal @optional
OP_TOKEN=
# @optional @sensitive
SIGNING_PASSWORD=op("op://Vault/Item/password")
⛔ SIGNING_PASSWORD  🔐sensitive
   └ undefined
   - error resolving value: SchemaError: op(): Unable to authenticate with 1Password
  1. Gating it with if() does not help when the plugin is only imported where it can authenticate:
# @type=boolean
SIGN=false
# @optional @sensitive
SIGNING_PASSWORD=if($SIGN, op("op://Vault/Item/password"))
   - Unknown resolver function: op()

The workaround is to put every op() reference in separate files, imported only when a flag is set (enabled=...), and to make every script set the right flag. It works, but it's a file per use case and a flag per script, just to stop lookups from running where they can't.

Proposed Solution
  • Opt-in per item or per plugin instance, e.g. @optional={onResolveError=undefined} or @initOp(..., optionalOnAuthFailure=true): an optional item whose resolver fails for a missing credential resolves to undefined and prints a warning. Required items still fail as today, so @required=forEnv(production) (or a flag) keeps releases strict.
  • Resolve function names lazily, so a plugin function in an if() branch that is not taken does not error when the plugin is not loaded.
Alternatives
  • Separate files per use case, imported behind flags (what we do now).
  • --filter per script to scope resolution, which moves the same bookkeeping into every script.
Additional Information

Typical case: code-signing credentials for an open-source app, where builds without credentials are expected to produce unsigned output.

Dominant language
TypeScript
Stars
4.9k
Forks
140
Avg merge
2d 3h
Merged PRs (30d)
35

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from dmno-dev/varlock

All issues in dmno-dev/varlock

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.