naro-cli 0.18.0 → 0.19.1

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 CHANGED
@@ -62,6 +62,7 @@ naro usage Team usage this month: requests, builds and c
62
62
  naro usage --month 2026-09 --team acme Another UTC month, another team
63
63
 
64
64
  naro deploy [--prod] Build locally and deploy
65
+ naro deploy --env qa Deploy to a named environment (<subdomain>--qa) instead of the preview; not with --prod
65
66
  naro deployments List deployments
66
67
  naro inspect <deployment-id> One deployment + build logs
67
68
  naro cancel <deployment-id> Stop a build that is still running
@@ -86,10 +87,27 @@ naro protection Preview protection: on or off, and whether a
86
87
  naro protection enable | disable Protect the preview URL (members only) or open it to anyone with the link (disable asks first; --yes in CI)
87
88
  naro protection bypass [remove] Create (shown once) or remove the secret automation sends as x-naro-protection-bypass (replacing or removing asks first; --yes in CI)
88
89
 
89
- naro env list [--reveal] Secrets masked unless --reveal
90
+ naro env list [--reveal] Secrets masked unless --reveal; an environment's value shows its name
90
91
  naro env add DATABASE_URL production
91
- naro env remove DATABASE_URL
92
- naro env pull [.env.local]
92
+ Target: production, preview, all (the default) or an environment name (qa)
93
+ naro env remove DATABASE_URL The production, preview and all values; an environment's only with its name
94
+ (naro env remove DATABASE_URL qa)
95
+ naro env pull [.env.local] Preview's values by default; --env production, or --env qa for an environment
96
+ (its own value wins over all; an unknown name fails before anything is written,
97
+ and so does a value no dotenv line reads back)
98
+ naro env import .env.qa qa Upload every variable in a dotenv file to one target (all by default; asks first,
99
+ --yes in CI; an unclosed quote, an invalid key, ASSETS or a value over 5 KB
100
+ stops it before any request, and so does a key a storage binding already uses
101
+ when there are over 100 variables; an empty value is uploaded and shown (empty))
102
+
103
+ naro environments List the project's environments: address, branch, protection, and how many the plan allows
104
+ naro environments create qa --branch qa
105
+ A QA or staging surface served at <subdomain>--qa; --copy-env preview|production|none
106
+ picks where its variables start, --database schema|empty how its database does
107
+ naro environments set qa --no-branch --protection off
108
+ Change the branch whose pushes deploy here (--branch <b>, or --no-branch for none)
109
+ and who can open it (--protection on|off; off asks first, --yes in CI)
110
+ naro environments delete qa Delete it with its worker and protection key (asks first; --yes in CI)
93
111
 
94
112
  naro domains list
95
113
  naro domains add www.example.com Prints the CNAME to create; naro connects
@@ -187,6 +205,8 @@ naro storage bucket list | empty <name> | remove <name> [--empty] (empty and r
187
205
  naro storage ls naro://avatars/u1 [--recursive] [--search <text>] Names that start with <text>, ASCII case ignored
188
206
  naro storage cp ./me.png naro://avatars/u1/me.png [--upsert] Up to the object limit, under 4 GiB (over 50 MiB in parts), with the service key
189
207
  naro storage cp naro://docs/team-1/plan.pdf ./ Replaces a local file of the same name
208
+ naro storage cp naro://docs/a.pdf naro://docs/b.pdf [--upsert] Inside one bucket, up to 5 GiB − 5 MiB
209
+ naro storage mv naro://docs/a.pdf naro://docs/old/a.pdf Inside one bucket, up to 5 GiB − 5 MiB; never replaces
190
210
  naro storage rm naro://avatars/u1/old.png [--recursive] (asks first)
191
211
  naro storage rm naro://avatars/u1/ --recursive Everything under u1/; written u1, an object u1 too
192
212
 
@@ -310,16 +330,15 @@ point at its table's primary key or a unique column. `--owner user_id` adds
310
330
  four actions; any other new table is closed to the Data API until you give it
311
331
  a policy (`CREATE POLICY` in a migration, or `naro policy create` or
312
332
  `naro policy set`; the command says so).
313
- Policies are kept by table name: a drop removes the table's policies whenever
314
- the project has a backend, on or off (the command says so). A rename leaves
315
- them under the old name, where they apply to no table — the command prints
316
- what to run to move them. Move them then: the next time `naro db table`
317
- creates a table as that name or renames one to it, renaming the table back
318
- included, the policies stored under the name are removed first, so a new
319
- table never inherits an earlier one's (except, on a project without a
320
- backend, one changed through `naro db table`, the table editor or MCP) — and
321
- neither does a table made by `naro db push` or `naro db query`. Whatever a command removes it prints
322
- so it can be made again: as `CREATE POLICY` statements, which
333
+ Policies go with their table, as in Postgres and as `naro db push` does it,
334
+ in the same migration: a drop removes the table's policies, a rename
335
+ moves them to the new name and rewrites the policies of other tables that
336
+ read it, and `rename-column` rewrites every policy that reads the column,
337
+ an owner rule's column included (the command says which). A rename such a
338
+ policy cannot follow is refused before anything runs. A table the command creates, or renames onto a
339
+ name, never inherits what an earlier table of that name left there: that is
340
+ removed first. A change that fails changes no policy. Whatever a command
341
+ removes it prints so it can be made again: as `CREATE POLICY` statements, which
323
342
  `naro policy create` takes back, and — for owner rules, whose owner column
324
343
  `CREATE POLICY` cannot say — as the `naro policy set <table> … --owner <column>`
325
344
  command that sets them again. A statement that cannot be shown as it is (a
@@ -585,8 +604,15 @@ SQLite changes a column by building the table again — `CREATE TABLE
585
604
  __new_x`, copy the rows, `DROP TABLE x`, `ALTER TABLE __new_x RENAME TO x` — so
586
605
  the drop removes `x`'s policies and the rename does not bring them back. Write
587
606
  the `CREATE POLICY` statements again after the rename, in the same migration.
588
- A plain `ALTER TABLE a RENAME TO b` does not move them either: they stay under
589
- `a`, and `b` has none until you create them again.
607
+ A plain `ALTER TABLE a RENAME TO b` in a migration moves `a`'s policies to `b`,
608
+ and a policy of another table that reads `a` is written to read `b` — do not
609
+ create them again on `b`: a policy of the same name already there is refused.
610
+ `ALTER TABLE t RENAME COLUMN c TO d` writes every policy that reads `t.c` —
611
+ `t`'s own, another table's through a subquery, an owner rule's column — to
612
+ read `t.d`, so each keeps reading the column it read, as in Postgres. A rename
613
+ a policy cannot follow, such as giving a column the name of a dropped one that
614
+ a policy still reads, is refused before anything runs.
615
+ `naro db table`, the table editor and MCP do the same.
590
616
  The answer's `warnings` lists the policies a migration removed, with SQL you
591
617
  can paste; it also says when the project has no backend yet (the policies are
592
618
  saved and apply once `naro backend enable` turns it on) and when a policy was
@@ -743,7 +769,10 @@ into named policies; it also turns a backend that is off back on, so run
743
769
  `naro backend disable` again afterwards if it should stay off. `naro policy
744
770
  list` and `naro policy remove` work in the meantime. A migration or a query
745
771
  that holds a `CREATE POLICY` or `DROP POLICY` gets the same answer before
746
- anything runs; SQL without one runs as before.
772
+ anything runs, and so does any change that creates, drops or renames a table —
773
+ in SQL, `naro db table`, the table editor or MCP, with the backend on or off:
774
+ the stored rules apply by table name, and only `naro backend enable` clears
775
+ them. Other SQL runs as before.
747
776
 
748
777
  `naro policy set` refuses with `409 POLICY_EXISTS` when the table's `naro_<action>` policy is not one it wrote (for example one made with `naro policy create`): `Policy <name> on <table> is not one naro policy set wrote. Change it with naro policy create, or drop it first: naro policy drop <name> --table <table>.` A `naro_<action>` policy that cannot be read as stored (the table answers `500 POLICY_INVALID`) is not refused: setting a rule replaces it, and `none` drops it.
749
778
 
@@ -808,6 +837,340 @@ An `--update-check` you give replaces the default: without
808
837
 
809
838
  ## Release notes
810
839
 
840
+ ### 0.19.1
841
+
842
+ 0.19.0 went out on 2026-10-19 without these.
843
+
844
+ - `naro git connect` says what to do when the link alone is not enough. The
845
+ control plane now records, for each team, only the repositories the people
846
+ who connected GitHub could read themselves (known-issues #232), and for an
847
+ account the team already holds it hands out an import link
848
+ (`/api/github/authorize`) rather than an install one. Without a terminal
849
+ or with `--json` the error reads
850
+ `Naro cannot reach <owner/repo> yet. Open <url> to give Naro access (if the repository is not among the ones the Naro GitHub App was granted on GitHub, add it there first), then run: naro git connect`
851
+ (0.19.0: `… Install the Naro GitHub App at <url>, then run: naro git connect`);
852
+ in a terminal, after `Opening <url>`, it adds
853
+ `If the repository is not among the ones the Naro GitHub App was granted on GitHub, add it there first.`
854
+ - `deployDirectory`, the library export the MCP server uses, now refuses
855
+ `production: true` with any `environment` (`""` too):
856
+ `VALIDATION_FAILED` `environment and production cannot be used together.`,
857
+ the control plane's own words, before any value is read, asked for or
858
+ sent and before the deployment is created (the MCP `deploy` tool still
859
+ signs in and looks the team up first). 0.19.0 sent both and left the
860
+ refusal to the control plane (a caller passing `onMissingEnv` was asked
861
+ for missing values first); a control plane from before named
862
+ environments 1b-2 ignores `environment` and would deploy to production.
863
+ - `naro env remove KEY` with no target, for a key only environments hold,
864
+ fails `ENV_NOT_FOUND`
865
+ `No KEY variable found outside named environments. Pass the environment to remove it: qa, staging.`
866
+ (`--json` details: `key`, `environments`) and still removes nothing. It
867
+ said `No KEY variable found.`, which a key no row has still gets.
868
+ - `naro env import` refuses more before any request, in this order:
869
+ `Cannot read <file>.`, `Unclosed quote in <file> at line <n>.`,
870
+ `No variables found in <file>.`, `Invalid keys in <file>: A-B, 1X.`,
871
+ `ASSETS is reserved for the project's static files; pick another name.`
872
+ (the env route's words) or `Values over 5 KB in <file>: BIG.` An empty
873
+ value (`KEY=`) is uploaded like any other and listed as `(empty)`, so a
874
+ file `naro env pull` wrote for a project holding one imports back. Past
875
+ 100 variables, and after you say yes, it reads the project's binding
876
+ names once (its storage bindings, `ASSETS`, and `DB` on a project with
877
+ the managed database) and fails `VALIDATION_FAILED`
878
+ `<KEY> is already used by a storage binding.` for the first key of the
879
+ file that is one, before the first request; the route refuses such a
880
+ key per request, which left the batches before it saved. Up to 100
881
+ variables ask nothing: one request is atomic on the server. Any other
882
+ refusal of a later request (a role, a race) still leaves the earlier
883
+ ones saved.
884
+ - Dotenv files are read the way Next.js reads them (dotenv 16, what
885
+ `next dev` runs), for `naro env import` and for the values `naro deploy`
886
+ reads from `.env.local` once you agree, so the value saved is the one
887
+ your app saw locally. A value in `'`, `"` or `` ` `` runs to its closing
888
+ quote over several lines (a PEM key, as `.env.local` for Next.js often
889
+ holds one). Inside double quotes `\n` and `\r` are a line break and a
890
+ carriage return and every other backslash stays as written (`\\` is two,
891
+ `\"` a backslash and a quote); single quotes and backticks are read as
892
+ written. An unquoted value ends at its first `#` (`abc#def` is `abc`).
893
+ CRLF ends a line, inside quotes too. A quote that never closes stays in
894
+ the value, as Next.js reads it (`naro env import` refuses the file). Unlike
895
+ Next.js, `$VAR` and `${VAR}` are not expanded: a value built from another
896
+ variable is saved as written. Before, a multi-line value was cut to its
897
+ first line, opening quote included, and a base64 line ending in `=`
898
+ became a key of its own.
899
+ - `naro env pull` writes each value so that dotenv and `naro env import`
900
+ read it back as it was (known-issues #224): bare when nothing in it needs
901
+ quoting, else in single quotes, in backticks when it holds `'`, or in
902
+ double quotes when it holds `'` and `` ` ``. A value with a carriage
903
+ return is written in double quotes with the carriage return as `\r`
904
+ (dotenv reads a carriage return written as is for a line break). A value
905
+ ending in a backslash is written bare. Next.js reads every value back as
906
+ it was except those with a `$`: it expands `$NAME` and `${NAME}`
907
+ (dotenv-expand) whatever the quotes, so a bcrypt hash `$2b$10$…` is cut
908
+ down (to `""`, or to what follows its first `.` or `/`) and `pa$$word` is
909
+ `pa$` for `next dev`, while `naro env import` reads them
910
+ unchanged. A value no dotenv line reads back fails before the overwrite
911
+ question and before anything is written, with `VALIDATION_FAILED`
912
+ ``Cannot write KEY1, KEY2 to a dotenv file: their values hold ', " and ` together.``
913
+ or, for the rarer carriage return beside `"`, backslash at the end, or
914
+ written-out `\n` beside `'` and `` ` ``,
915
+ `Cannot write KEY to a dotenv file: dotenv would not read their values back unchanged.`
916
+ followed by how to store such a value: without carriage returns or one of
917
+ the quote characters (a service-account JSON from a CRLF file:
918
+ `tr -d '\r' < sa.json | naro env add KEY`), or read it with
919
+ `naro env list --reveal` (`--json` details: `keys`). Before, it wrote such
920
+ values in double quotes with `\` and `"` escaped, which Next.js reads with
921
+ the backslashes: pull a file an earlier version wrote
922
+ again.
923
+ - On a backend from before named policies, renaming a column answers
924
+ `409 BACKEND_OUTDATED` until `naro backend enable` runs, as creating,
925
+ dropping or renaming a table does — through `naro db table`,
926
+ `naro db push` and `naro db query` alike.
927
+ - `naro db table rename-column`, and `ALTER TABLE … RENAME COLUMN` in
928
+ `naro db push` and `naro db query`, rewrite the Data API policies that read
929
+ the column, an owner rule's column included (known-issues #90): the
930
+ command prints
931
+ `⚠ Rewrote 1 policy that read members.user_id to read members.uid: docs.team.`.
932
+ Before, a policy reading the old name answered `500 POLICY_INVALID`, and
933
+ two columns swapped in one change left it reading the other column. The
934
+ warning that told you to run `naro policy set <table> --owner <new>` is
935
+ gone. A rename a policy cannot follow is refused before anything runs.
936
+ - `naro db push` and `naro db reset` check a migration's `ALTER TABLE …
937
+ RENAME` the way the control plane now reads it: a column rename whose
938
+ names cannot be read (`ALTER TABLE t RENAME COLUMN c TO` with nothing
939
+ after it, `t.c` for the column) is
940
+ `Statement <i> of <n>: the column name could not be read.` before anything
941
+ runs. Before, it reached D1 and failed as SQLite's syntax error.
942
+ - `naro storage mv naro://<bucket>/<from> naro://<bucket>/<to>` moves an
943
+ object inside its bucket, and `naro storage cp` between two `naro://`
944
+ paths of one bucket copies one there (Storage 3-1i), each up to
945
+ 5 GiB − 5 MiB. Over that the backend answers `413 OBJECT_TOO_LARGE`:
946
+ `Objects over 5,363,466,240 bytes (5 GiB − 5 MiB) cannot be copied or moved.`
947
+ A destination ending in `/`, or the bucket alone (`naro://docs`), takes the
948
+ object's name. `mv` never replaces an
949
+ object — a name that is taken answers `409 OBJECT_EXISTS`
950
+ `Object <path> already exists in bucket <bucket>. A move never replaces an object: remove it or choose another name.`
951
+ — and takes no `--upsert`, `--content-type` or `--cache-control`; `cp`
952
+ replaces one with `--upsert` and keeps the type and cache-control
953
+ (`--content-type` and `--cache-control` are refused).
954
+ Both refuse two buckets before any request:
955
+ `naro storage cp and mv work inside one bucket: both sides must be in naro://<bucket>.`
956
+ A name an upload or a download would refuse is refused before any request,
957
+ in the same words (`INVALID_PATH`
958
+ `The object path is not valid: it has an empty segment (//).`), and
959
+ `--recursive` is refused rather than dropped:
960
+ `naro storage mv takes no --recursive: it moves one object, naro://<bucket>/<path>. --recursive is for naro storage ls and rm.`
961
+ (`cp` between two `naro://` paths:
962
+ `A copy inside Storage takes no --recursive: it copies one object, naro://<bucket>/<path>. --recursive is for naro storage ls and rm.`).
963
+ A project backend from before this release answers them with
964
+ `BACKEND_OUTDATED`:
965
+ ``The project backend is older than this Storage command. Run `naro backend enable` to update it, then try again.``
966
+ `cp` between two `naro://` paths used to answer
967
+ `Copying inside Storage is not supported yet.` `--json` of a copy carries
968
+ `object` (`{ id, path, fullPath }`).
969
+ - `naro db lint` measures a `storage.objects` move too (Storage 3-1i): a
970
+ move binds its new name at every read of the UPDATE policy's check, so a
971
+ set whose UPDATE check reads `name` many times can now be refused before
972
+ it is pushed, though an overwrite under it fits; the backend would answer
973
+ every move `500 POLICY_INVALID`. A copy's claim is an upload's and changes
974
+ nothing.
975
+ - A table's policy can read `storage.objects` in a subquery (Storage 3-1j),
976
+ and so can a `realtime.messages` policy. `naro db push --dry-run`,
977
+ `naro db reset` and `naro policy create` take such a policy here, where
978
+ 0.18.0 and 0.19.0 refused it locally, before changing anything, with
979
+ `A policy cannot read storage.objects in a subquery yet at character <n>.`,
980
+ and `naro db lint` no longer reports a stored one as `rls_policy_invalid`
981
+ (known-issues #227). `naro db reset` lists a stored one your files do not
982
+ make with the SQL that keeps it, where 0.18.0 and 0.19.0 showed
983
+ `-- Policy <p> on <t> cannot be read (…)` in its place (in `--json` too)
984
+ and, once confirmed, dropped it with no SQL to make it again. The backend reads it through the caller's
985
+ `storage.objects` policies and only files that are fully there (not still
986
+ uploading or being removed); write `bucket_id = '<bucket>'` in the
987
+ subquery (`bucket_id in ('a', 'b')` for several buckets). A check never
988
+ finds a new file being uploaded or copied, or a move's new name, as in
989
+ Postgres. A backend
990
+ from before Storage 3-1j answers such a policy with
991
+ `409 BACKEND_OUTDATED`:
992
+ ``storage.objects is not available on this backend yet. Run `naro backend enable` to update it.``
993
+ `naro db lint` measures those policies inside the table's statement, and
994
+ for a signed-in caller whose email is not verified too.
995
+ - `naro db reset` refuses, before it drops anything (and on `--dry-run`
996
+ too), migration files the backend would stop at for Storage: a policy that
997
+ reads `storage.objects` in a subquery while the backend's ledger lacks
998
+ system migration 7 (it reads the ledger only when a file has one), and
999
+ any statement on `storage.objects` (CREATE POLICY, DROP POLICY without
1000
+ IF EXISTS, the `naro:owner` COMMENT) on a backend from before Storage or a
1001
+ project with none. It fails `BACKEND_OUTDATED`
1002
+ ``0002_b.sql needs storage.objects (statement 2 of 2), which is not available on this backend yet, so the reset would stop there with the schema already dropped. Nothing was changed. Run `naro backend enable` to update it, then try again.``
1003
+ (`--json` details: `migration`, `statement`). Before, the checks passed,
1004
+ the schema was dropped and the re-apply stopped at the control plane's
1005
+ `409 BACKEND_OUTDATED`, with `The schema is dropped and the re-apply stopped.`
1006
+
1007
+ ### 0.19.0
1008
+
1009
+ - `naro environments` manages a project's named environments, QA or staging
1010
+ surfaces served at `https://<subdomain>--<slug>.naro.sh` beside production
1011
+ and the preview. While the control plane has them switched off, every
1012
+ sub-command fails with the server's `404 NOT_FOUND "Not found."`.
1013
+ - `naro environments` (also `list`, `ls`) prints
1014
+ `slug url branch protection` and one row per environment (`—` when no
1015
+ branch deploys there, protection `on` or `off`), then
1016
+ `2 of 3 environments`, or `2 environments` (`1 environment`) on a plan
1017
+ with no limit. With none it prints
1018
+ ``No environments. Create one with `naro environments create qa`.``
1019
+ first. `--json` prints `{ projectId, environments, limit }`.
1020
+ - `naro environments create qa [--branch qa] [--copy-env preview|production|none] [--database schema|empty]`
1021
+ prints `✅ Created environment qa → https://<subdomain>--qa.naro.sh`. A
1022
+ flag left out leaves the server's default: no branch, the preview's
1023
+ variables, the database seeded with the schema. `--copy-env none` copies
1024
+ nothing. Other values fail before any request with
1025
+ `--copy-env must be preview, production or none.` and
1026
+ `--database must be schema or empty.`
1027
+ - `naro environments set qa [--branch <b> | --no-branch] [--protection on|off]`
1028
+ prints `✅ Updated environment qa`. Before any request it refuses
1029
+ `--branch and --no-branch cannot be used together.`,
1030
+ `--protection must be on or off.` and
1031
+ `Nothing to change: pass --branch, --no-branch or --protection.`
1032
+ `--protection off` asks
1033
+ `Turn off protection for qa? Anyone with the link can open it.` first,
1034
+ like `naro protection disable`; with `--json` or without a terminal it
1035
+ needs `--yes` (`CONFIRMATION_REQUIRED`).
1036
+ - `naro environments delete qa` asks
1037
+ `Delete environment qa? Its worker and protection key are removed.`,
1038
+ then prints `✅ Deleted environment qa` (`--json`:
1039
+ `{ projectId, slug, deleted: true }`).
1040
+ - A slug the project does not have fails `ENVIRONMENT_NOT_FOUND`
1041
+ `Environment not found.` and changes nothing. The server's refusals
1042
+ come through with their code and message, such as `ENVIRONMENT_EXISTS`
1043
+ `An environment with this name already exists.` and
1044
+ `ENVIRONMENT_BRANCH_TAKEN`
1045
+ `Another environment already deploys this branch.`
1046
+ - New options `--no-branch`, `--copy-env <source>`, `--database <seed>`
1047
+ and `--protection <on|off>`. `--branch <b>` is in `naro help` now, and
1048
+ says what it does: for `naro environments create` and `set`, the branch
1049
+ whose pushes deploy to that environment; for `naro deploy`, the default
1050
+ branch of a project the deploy creates or updates. A deploy's own branch
1051
+ follows where it goes.
1052
+ - `naro deploy --env qa` deploys to a named environment instead of the
1053
+ preview. It prints `✅ Deployment ready (qa)`, and `--json` has
1054
+ `"target": "qa"` and `"environment": "qa"` (`null` for production and
1055
+ preview). When the server gives no URL the CLI builds
1056
+ `https://<subdomain>--qa.<host>`. `--env production` is `--prod` (and asks
1057
+ `Deploy to production?` in a terminal the same way); `--env preview` is a
1058
+ plain deploy. `--env` with `--prod` fails before anything is asked or sent:
1059
+ `VALIDATION_FAILED` `--env and --prod cannot be used together.`, and
1060
+ `--env ""` with `--env must be production, preview or an environment name.`
1061
+ In a linked directory the environment is looked up before a missing key is
1062
+ read, asked for or sent, and nothing is asked, sent or built when that
1063
+ fails: a name the project has no environment for fails
1064
+ `ENVIRONMENT_NOT_FOUND` `Environment not found.`, and while the control
1065
+ plane has named environments switched off the deploy fails with their
1066
+ `404 NOT_FOUND "Not found."`. Not yet linked, an environment deploy asks
1067
+ for no missing value and sends none (the hint names the environment), and
1068
+ the server answers `404 ENVIRONMENT_NOT_FOUND "Environment not found."`
1069
+ for a name the project does not have.
1070
+ - Release order: deploy web with named environments 1b-2 before relying on
1071
+ `naro deploy --env`. The deploy route of an older control plane ignores
1072
+ the name and deploys a preview (the result says `(preview)`), saving the
1073
+ values sent with it for `all`, which production builds read. In a linked
1074
+ directory the environments route's 404 stops the deploy before that, and
1075
+ an unlinked one sends no values.
1076
+ - `deployDirectory`, the library export the MCP server uses, refuses
1077
+ `environment: "production"` and `environment: "preview"` (without
1078
+ `production: true`) with `VALIDATION_FAILED`
1079
+ `Pass production: true for production; preview is the default.` With
1080
+ `production: true` the control plane answers
1081
+ `environment and production cannot be used together.`
1082
+ - `naro deploy` counts the env vars a deploy is missing from the values that
1083
+ deploy gets. A production deploy now lists a key set only for preview as
1084
+ missing, and a preview deploy one set only for production; an environment
1085
+ deploy counts the `all` values and that environment's own. On an
1086
+ environment deploy, the values the deploy reads from your dotenv file
1087
+ (once you agree to it) are saved for that environment alone, so a
1088
+ developer, who cannot change `all`, has them saved instead of listed under
1089
+ `⚠ skipped env:`. Production and preview deploys
1090
+ still save them for `all`. The hint names the environment too:
1091
+ `npx naro-cli env add DATABASE_URL qa`.
1092
+ - `naro env add` and `naro env remove` take an environment's slug as the
1093
+ target: `naro env add DATABASE_URL qa`. A target that is none of
1094
+ `production`, `preview`, `all` or a slug fails with
1095
+ `Target must be production, preview, all or an environment name.` (it was
1096
+ `Environment must be production, preview or all.`), and the usage reads
1097
+ `Usage: naro env add KEY [production|preview|all|<environment>]`.
1098
+ `naro env list` shows an environment's value under its slug.
1099
+ - `naro env remove KEY` with no target removes the `production`, `preview`
1100
+ and `all` values and leaves every environment's alone; remove one with
1101
+ `naro env remove KEY qa` (`Remove KEY (qa) from this project?`). A key
1102
+ that only environments hold fails `ENV_NOT_FOUND` `No KEY variable found.`
1103
+ and nothing is removed.
1104
+ - `naro env pull --env qa` writes an environment's values. A surface's own
1105
+ value now wins over the `all` one whatever order the server lists them in
1106
+ (before, the last row won), and preview's values never reach an
1107
+ environment, as in the deploy. An environment the project does not have
1108
+ fails `ENVIRONMENT_NOT_FOUND` `Environment not found.` before anything is
1109
+ written. `--env` takes `production`, `preview` or a slug; anything else,
1110
+ `""` included, fails with
1111
+ `--env must be production, preview or an environment name.` (it was
1112
+ `--env must be production or preview.`, and `--env ""` pulled preview).
1113
+ The count in `✅ Pulled N variable(s)` and `--json` is the keys written,
1114
+ so a key held by `all` and the surface counts once.
1115
+ - `naro env import <file> [target]` uploads every variable in a dotenv file
1116
+ to one target, `all` by default. It lists the keys on stdout (stderr with
1117
+ `--json`), every value masked but a `NEXT_PUBLIC_` one: the others,
1118
+ `VITE_`, `REACT_APP_` and `PUBLIC_` included, are uploaded as secrets. It
1119
+ asks `Upload 3 variables to qa?` (`1 variable`; `--yes` in CI),
1120
+ and prints `✅ Imported 3 variables (qa)` (`--json`:
1121
+ `{ projectId, file, target, count }`). Before any request it fails with
1122
+ `Cannot read <file>.`, `No variables found in <file>.`,
1123
+ `Invalid keys in <file>: A-B, 1X.` or
1124
+ `Values over 5 KB in <file>: BIG.` (5,120 UTF-8 bytes, the limit the
1125
+ server keeps). It uploads 100 variables per request, so a refusal of a
1126
+ later request leaves the earlier ones saved. A line `export KEY=value`
1127
+ reads as `KEY`. Values with `\"` or `\\` inside double quotes are read as
1128
+ written, not unescaped, so a file `naro env pull` wrote with such a value
1129
+ does not import back as it was (known-issues #224).
1130
+ A value in quotes that runs over several lines (a PEM key) is cut to
1131
+ its first line, opening quote included, and a base64 line ending in
1132
+ `=` becomes a key of its own, though the result says `✅ Imported`.
1133
+ The values `naro deploy` reads from `.env.local` once you agree are cut
1134
+ the same way, with no warning. Use 0.19.1 for such a file.
1135
+ - `naro env add` with a value typed at the prompt no longer loses it to a
1136
+ refusal. It reads the project first, so a `--project` of another team or
1137
+ of a deleted project fails `404 NOT_FOUND "Project not found."` before the
1138
+ value is asked for. For an environment target it looks the environment up
1139
+ too: a slug the project does not have fails `ENVIRONMENT_NOT_FOUND`
1140
+ `Environment not found.` before the value is asked for, and while
1141
+ environments are switched off `404 NOT_FOUND "Not found."` does. When the
1142
+ role cannot write `all` (the default, or typed out), it asks
1143
+ `You do not have permission to change production environment variables on this project. Save KEY for preview only?`
1144
+ and on yes saves the same value for preview (`✅ Added KEY (preview, secret)`).
1145
+ A named `production`, `preview` or environment target is not offered
1146
+ another. A piped value works as before.
1147
+ - `naro usage` names a project that has moved to another team
1148
+ `Moved to another team <id>`. Before, it read `Deleted project <id>`.
1149
+ - `naro usage` prints `<1%` for a meter that is used but under 1% of its
1150
+ limit (9,056 of 1,000,000 requests). Before, it printed `0%`, as if
1151
+ nothing had been used.
1152
+ - `naro db reset` reads the migration files the way the control plane now
1153
+ runs them: `ALTER TABLE a RENAME TO b` moves `a`'s policies to `b`
1154
+ (known-issues #87), so a policy a renamed table took along is no longer
1155
+ listed as gone after the reset. A file that creates one of them again on
1156
+ `b`, as the old advice said, would now stop the re-apply, and is named
1157
+ before the schema is dropped:
1158
+ `⚠ <file> would be refused: statement <n> of <m> failed and the migration was rolled back: policy "<name>" for table "b" already exists`.
1159
+ - `naro db table rename` moves the table's Data API policies to the new name
1160
+ and rewrites the policies of other tables that read it, in the same
1161
+ migration, as `naro db push` does (known-issues #87): the command prints
1162
+ `⚠ Moved 1 Data API policy with posts to articles: own.` and
1163
+ `⚠ Rewrote 1 policy that read posts to read articles: docs.team.`. A rename
1164
+ a policy cannot follow is refused before anything runs. Before, the
1165
+ policies stayed under the old name and the table was closed. Renaming the
1166
+ table back brings them back.
1167
+ - `naro db table create`, `drop` and `rename` no longer print policies
1168
+ "removed before the change ran" when the change fails: a change that fails
1169
+ changes no policy now.
1170
+ - On a backend from before named policies, creating, dropping or renaming a
1171
+ table answers `409 BACKEND_OUTDATED` until `naro backend enable` runs —
1172
+ through `naro db table`, `naro db push` and `naro db query` alike.
1173
+
811
1174
  ### 0.18.0
812
1175
 
813
1176
  - `naro usage` shows a team's usage for a UTC month from the terminal:
@@ -866,8 +1229,9 @@ An `--update-check` you give replaces the default: without
866
1229
  `buildCode`, the code the dashboard shows. It is a deployment error code,
867
1230
  such as `NEXT_VERSION_UNSUPPORTED`, `INSTALL_FAILED`, `BUILD_FAILED`,
868
1231
  `ARTIFACT_INVALID` (static output a deploy cannot take, like a symbolic
869
- link), `FRAMEWORK_DETECTION_FAILED`, or `NO_DEPLOYMENT_STRATEGY` when every
870
- deployment strategy of a Next.js app failed. Before, the stage's code was
1232
+ link), `FRAMEWORK_DETECTION_FAILED`, or `NO_DEPLOYMENT_STRATEGY` when a
1233
+ Next.js app's own build did not fail but no deployment strategy could ship
1234
+ it (its own `next build` failing is `BUILD_FAILED`). Before, the stage's code was
871
1235
  only in the message. A failed upload still fails with its own error and no
872
1236
  `buildCode`; the dashboard shows its deployment code, or `DEPLOY_FAILED`.
873
1237
  - `naro storage ls naro://<bucket>[/<prefix>] --search <text>` lists only the
@@ -1186,12 +1550,13 @@ Next.js), `INSTALL_FAILED` (the dependency install), `ARTIFACT_INVALID` (static
1186
1550
  output a deploy cannot take, like a symbolic link), `FRAMEWORK_DETECTION_FAILED`
1187
1551
  (no framework found, or an Angular app without an output path) and
1188
1552
  `BUILD_FAILED` (the app's own build, or a failure that carried no code). A
1189
- Next.js app is built by trying deployment strategies in turn, so when
1190
- every one fails — the app's own build error included — `buildCode` is
1191
- `NO_DEPLOYMENT_STRATEGY` and the message says what each strategy failed at.
1553
+ Next.js app is built by trying deployment strategies in turn: when the app's
1554
+ own `next build` fails, `buildCode` is `BUILD_FAILED`; when its own build did
1555
+ not fail but no strategy can ship it, `NO_DEPLOYMENT_STRATEGY`. Either way the message says
1556
+ what each strategy failed at.
1192
1557
 
1193
1558
  `--yes` (or `-y`) suppresses every prompt — destructive actions
1194
- (production rollback/promote, env/domain removal, database reset, backend key
1559
+ (production rollback/promote, env/domain/environment removal, `naro env import`, turning off an environment's protection, database reset, backend key
1195
1560
  rotation, policy removal and drop, opening the preview with
1196
1561
  `naro protection disable`, replacing or removing the bypass secret) run
1197
1562
  unconfirmed, so use it deliberately in
@@ -1215,9 +1580,11 @@ credentials live in `~/.naro/credentials.json` (0600).
1215
1580
 
1216
1581
  - Values are entered via hidden prompt or stdin — never as an argument:
1217
1582
  `echo "$DATABASE_URL" | naro env add DATABASE_URL production --yes`
1218
- - Targets: `production`, `preview`, `all` (default).
1583
+ - Targets: `production`, `preview`, `all` (default), or a named
1584
+ environment's slug: `naro env add DATABASE_URL qa`.
1219
1585
  - `naro env pull` writes `.env.local` (preview + all vars by default,
1220
- `--env production` for production values).
1586
+ `--env production` for production values, `--env <name>` for an
1587
+ environment's).
1221
1588
 
1222
1589
  ## Configuration
1223
1590
 
@@ -1225,5 +1592,5 @@ credentials live in `~/.naro/credentials.json` (0600).
1225
1592
  | ------------------------ | ---------------------------------------------- |
1226
1593
  | `NARO_TOKEN` | CI/agent access token (skips `naro login`) |
1227
1594
  | `NARO_CONTROL_PLANE_URL` | Custom control plane (default https://naro.sh) |
1228
- | `NARO_SERVICE_KEY` | Service key for `naro storage ls\|cp\|rm` |
1595
+ | `NARO_SERVICE_KEY` | Service key for `naro storage ls\|cp\|mv\|rm` |
1229
1596
  | `NARO_SUPABASE_URL/KEY` | Auth backend override (self-hosted setups) |