@myelinbridge/cli 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +105 -59
- package/bin/myelin.js +616 -496
- package/package.json +23 -23
package/README.md
CHANGED
|
@@ -1,59 +1,105 @@
|
|
|
1
|
-
# @myelinbridge/cli
|
|
2
|
-
|
|
3
|
-
Push R&D data deliveries into [Myelin](https://myelinbridge.com) from a pipeline —
|
|
4
|
-
preflight against the client's published quality rules, resumable upload, submit,
|
|
5
|
-
and track review outcomes. Full API reference: https://myelinbridge.com/developers.
|
|
6
|
-
|
|
7
|
-
## Quick start (~10 minutes from key to first submit)
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
export MYELIN_API_KEY=myl_live_… # created by your bridge owner in Bridge → API
|
|
11
|
-
|
|
12
|
-
npx @myelinbridge/cli ping # verifies auth, prints your projects
|
|
13
|
-
npx @myelinbridge/cli datasets # what you can deliver to, and whose move it is
|
|
14
|
-
npx @myelinbridge/cli contract --dataset onco1-wes # what is expected of your delivery
|
|
15
|
-
npx @myelinbridge/cli sample-depth 1 --dataset onco1-wes # once, before your first submit
|
|
16
|
-
npx @myelinbridge/cli check ./run_042 --dataset onco1-wes # validate BEFORE uploading a byte
|
|
17
|
-
npx @myelinbridge/cli push ./run_042 --dataset onco1-wes --submit
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
- **Declare your sample depth once, first.** The client creates and describes the
|
|
21
|
-
dataset; you own your output structure, so you tell Myelin at which folder depth a
|
|
22
|
-
sample sits — `0` = the delivery root is one sample, `1` (default) = each top-level
|
|
23
|
-
folder is a sample, `2` = one level deeper. Sample-scoped quality checks group by it,
|
|
24
|
-
so getting it right up front is what makes per-sample verdicts mean anything. It is
|
|
25
|
-
**idempotent** (safe to assert on every pipeline run) and **locks once your first
|
|
26
|
-
batch leaves draft**, so that verdicts stay comparable across deliveries — after that
|
|
27
|
-
the command exits `2`. This is the only dataset field you can write.
|
|
28
|
-
|
|
29
|
-
- **Resume = re-run.** `push` is idempotent: already-uploaded files are skipped
|
|
30
|
-
(path + size), and within a large file, parts that already landed are skipped
|
|
31
|
-
too (S3 multipart). Uploads go direct to storage over short-lived presigned
|
|
32
|
-
URLs — no credential is stored on your machine, and revoking the API key cuts
|
|
33
|
-
off signing immediately.
|
|
34
|
-
- **Read the contract before you build the delivery.** `contract` prints what the
|
|
35
|
-
client expects — every check as one plain sentence, grouped by what it answers
|
|
36
|
-
(completeness, structure, validity, consistency, integrity, privacy), and marked
|
|
37
|
-
`!` when a failure blocks validation. It also tells you which checks `check` can
|
|
38
|
-
verify locally and which only run once the files are uploaded, so nothing about
|
|
39
|
-
the bar is a surprise at review time.
|
|
40
|
-
|
|
41
|
-
- **`check` costs nothing.** It evaluates your local
|
|
42
|
-
quality checks server-side — same engine, same verdicts as submit — without
|
|
43
|
-
uploading. Exit code 2 means a blocking rule fails.
|
|
44
|
-
- **The fix loop is machine-readable.** On `changes_requested`,
|
|
45
|
-
`myelin status <batch> --json` returns the failed files, reviewer comments, and
|
|
46
|
-
rule remediation hints; fix, re-`push --submit`, unchanged files keep their
|
|
47
|
-
review votes.
|
|
48
|
-
|
|
49
|
-
##
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
1
|
+
# @myelinbridge/cli
|
|
2
|
+
|
|
3
|
+
Push R&D data deliveries into [Myelin](https://myelinbridge.com) from a pipeline —
|
|
4
|
+
preflight against the client's published quality rules, resumable upload, submit,
|
|
5
|
+
and track review outcomes. Full API reference: https://myelinbridge.com/developers.
|
|
6
|
+
|
|
7
|
+
## Quick start (~10 minutes from key to first submit)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
export MYELIN_API_KEY=myl_live_… # created by your bridge owner in Bridge → API
|
|
11
|
+
|
|
12
|
+
npx @myelinbridge/cli ping # verifies auth, prints your projects
|
|
13
|
+
npx @myelinbridge/cli datasets # what you can deliver to, and whose move it is
|
|
14
|
+
npx @myelinbridge/cli contract --dataset onco1-wes # what is expected of your delivery
|
|
15
|
+
npx @myelinbridge/cli sample-depth 1 --dataset onco1-wes # once, before your first submit
|
|
16
|
+
npx @myelinbridge/cli check ./run_042 --dataset onco1-wes # validate BEFORE uploading a byte
|
|
17
|
+
npx @myelinbridge/cli push ./run_042 --dataset onco1-wes --submit
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
- **Declare your sample depth once, first.** The client creates and describes the
|
|
21
|
+
dataset; you own your output structure, so you tell Myelin at which folder depth a
|
|
22
|
+
sample sits — `0` = the delivery root is one sample, `1` (default) = each top-level
|
|
23
|
+
folder is a sample, `2` = one level deeper. Sample-scoped quality checks group by it,
|
|
24
|
+
so getting it right up front is what makes per-sample verdicts mean anything. It is
|
|
25
|
+
**idempotent** (safe to assert on every pipeline run) and **locks once your first
|
|
26
|
+
batch leaves draft**, so that verdicts stay comparable across deliveries — after that
|
|
27
|
+
the command exits `2`. This is the only dataset field you can write.
|
|
28
|
+
|
|
29
|
+
- **Resume = re-run.** `push` is idempotent: already-uploaded files are skipped
|
|
30
|
+
(path + size), and within a large file, parts that already landed are skipped
|
|
31
|
+
too (S3 multipart). Uploads go direct to storage over short-lived presigned
|
|
32
|
+
URLs — no credential is stored on your machine, and revoking the API key cuts
|
|
33
|
+
off signing immediately.
|
|
34
|
+
- **Read the contract before you build the delivery.** `contract` prints what the
|
|
35
|
+
client expects — every check as one plain sentence, grouped by what it answers
|
|
36
|
+
(completeness, structure, validity, consistency, integrity, privacy), and marked
|
|
37
|
+
`!` when a failure blocks validation. It also tells you which checks `check` can
|
|
38
|
+
verify locally and which only run once the files are uploaded, so nothing about
|
|
39
|
+
the bar is a surprise at review time.
|
|
40
|
+
|
|
41
|
+
- **`check` costs nothing.** It evaluates your local file list against the dataset's
|
|
42
|
+
quality checks server-side — same engine, same verdicts as submit — without
|
|
43
|
+
uploading. Exit code 2 means a blocking rule fails.
|
|
44
|
+
- **The fix loop is machine-readable.** On `changes_requested`,
|
|
45
|
+
`myelin status <batch> --json` returns the failed files, reviewer comments, and
|
|
46
|
+
rule remediation hints; fix, re-`push --submit`, unchanged files keep their
|
|
47
|
+
review votes.
|
|
48
|
+
|
|
49
|
+
## If you are the client, not the partner
|
|
50
|
+
|
|
51
|
+
Two kinds of key exist, and they are not interchangeable. Everything above needs a
|
|
52
|
+
**partner key** (write: upload, submit). A **client key** is read-only and answers the
|
|
53
|
+
question your own systems ask once the data has landed: *the bucket is full of UUIDs —
|
|
54
|
+
what is this?*
|
|
55
|
+
|
|
56
|
+
By default a client key is **organisation-wide**: one key, every partner, one answer. Your
|
|
57
|
+
organisation admin creates it in **Organisation → API keys**. If your governance is per-partner,
|
|
58
|
+
a bridge owner can create a bridge-scoped one instead in **Bridge → API → "Your read keys"**.
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
export MYELIN_API_KEY=myl_live_…
|
|
62
|
+
|
|
63
|
+
# What has landed, newest first
|
|
64
|
+
myelin deliveries --dataset <dataset-id>
|
|
65
|
+
|
|
66
|
+
# What is this object, exactly?
|
|
67
|
+
myelin resolve gs://acme-landing/inbox/acme-cro/4319…/de99…/7aa5…/data/SAMPLE_01/reads.fastq.gz
|
|
68
|
+
# file · gs://…/reads.fastq.gz
|
|
69
|
+
# project ONCO1 — Oncology discovery
|
|
70
|
+
# dataset WES batch 7 (Genomics)
|
|
71
|
+
# batch ONCO1-WES-007 · #7
|
|
72
|
+
# validated 2026-08-07T18:05:12Z · delivered 2026-08-07T18:06:20Z
|
|
73
|
+
# manifest gs://…/7aa5…/_myelin/manifest.json
|
|
74
|
+
# file reads.fastq.gz · 4096 bytes
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`resolve` accepts a full `gs://`/`s3://` URI, a bare prefix, or a single id, and answers at
|
|
78
|
+
whatever granularity the path supports.
|
|
79
|
+
|
|
80
|
+
Each delivery also carries the same record **as a file**, written next to the data at
|
|
81
|
+
`_myelin/manifest.json` (plus `_myelin/files.csv`, a flat table you can load straight into a
|
|
82
|
+
warehouse). Prefer the file for anything auditable: it is frozen at delivery time, needs no
|
|
83
|
+
credentials, and does not depend on Myelin being reachable. Use the API when you want it live.
|
|
84
|
+
|
|
85
|
+
A partner key calling these gets `403 wrong_key_side`, and vice versa.
|
|
86
|
+
|
|
87
|
+
## Machine mode
|
|
88
|
+
|
|
89
|
+
Every command takes `--json`. Exit codes: `0` ok · `1` error · `2` blocked
|
|
90
|
+
(blocking preflight failure, locked delivery, blocked submit, locked sample depth).
|
|
91
|
+
|
|
92
|
+
## Environment
|
|
93
|
+
|
|
94
|
+
| Variable | |
|
|
95
|
+
|---|---|
|
|
96
|
+
| `MYELIN_API_KEY` | Required. Created by your bridge owner in **Bridge → API**. |
|
|
97
|
+
| `MYELIN_API_URL` | Optional. Defaults to `https://myelinbridge.com/api/v1`. |
|
|
98
|
+
| `MYELIN_API_HEADER` | Optional. Extra headers sent with every API call, one `Name: value` per line — for a Myelin deployment fronted by something that authenticates before Myelin does (a corporate gateway, an SSO-protected preview). It can never override `Authorization`. |
|
|
99
|
+
|
|
100
|
+
## Webhooks instead of polling
|
|
101
|
+
|
|
102
|
+
Register an HTTPS endpoint (portal Bridge → API, or `POST /v1/webhook-endpoints`)
|
|
103
|
+
to receive signed events (`batch.validated`, `batch.changes_requested`,
|
|
104
|
+
`batch.transferred`, …). Verification snippets: https://myelinbridge.com/developers.
|
|
105
|
+
Polling fallback: `GET /v1/events?cursor=…`.
|