rowstile 0.1.0-alpha.3 → 0.1.0-alpha.5

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.
Files changed (39) hide show
  1. package/README.md +3 -2
  2. package/bin/rowstile.js +29 -1
  3. package/command/authzlib/__init__.py +4 -1
  4. package/command/authzlib/base.py +46 -7
  5. package/command/authzlib/compiler.py +577 -259
  6. package/command/authzlib/conditions.py +17 -8
  7. package/command/authzlib/connection.py +1 -0
  8. package/command/authzlib/coverage.py +12 -5
  9. package/command/authzlib/database.py +333 -124
  10. package/command/authzlib/devtools.py +15 -8
  11. package/command/authzlib/draft.py +235 -62
  12. package/command/authzlib/errors.py +201 -101
  13. package/command/authzlib/evaluate.py +92 -44
  14. package/command/authzlib/fmt.py +33 -16
  15. package/command/authzlib/governance.py +105 -50
  16. package/command/authzlib/grant.py +100 -52
  17. package/command/authzlib/hardening.py +122 -54
  18. package/command/authzlib/identity.py +22 -15
  19. package/command/authzlib/insight.py +161 -86
  20. package/command/authzlib/migrate.py +193 -102
  21. package/command/authzlib/output.py +376 -196
  22. package/command/authzlib/parse.py +249 -98
  23. package/command/authzlib/perf.py +78 -32
  24. package/command/authzlib/prove.py +23 -11
  25. package/command/authzlib/refusals.py +107 -48
  26. package/command/authzlib/review.py +361 -139
  27. package/command/authzlib/sqlutil.py +196 -33
  28. package/command/authzlib/statements.py +26 -19
  29. package/command/authzlib/testing.py +98 -45
  30. package/command/authzlib/trees.py +427 -275
  31. package/command/cli/init.py +27 -8
  32. package/command/cli/lsp.py +140 -51
  33. package/command/cli/mcp.py +107 -45
  34. package/command/cli/migrations.py +74 -21
  35. package/command/cli/pgwire.py +161 -67
  36. package/command/cli/rowstile_cli.py +351 -105
  37. package/command/cli/stack.py +67 -30
  38. package/command/cli/studio.py +258 -84
  39. package/package.json +30 -9
package/README.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # rowstile
2
2
 
3
- Access rules for Postgres: a policy language that the `rowstile` command compiles into row-level security, and
4
- ships as migrations for your app's tool (Prisma, Drizzle Kit, Alembic, SQL files).
3
+ Authorization for Postgres apps: access rules in a policy language that the `rowstile` command compiles into
4
+ row-level security, and ships as migrations for your app's tool (Prisma, Drizzle Kit, Alembic, SQL files).
5
+ Sharing, groups, nested folders and tenants, with no service to run beside the database.
5
6
 
6
7
  npx rowstile init # a first policy from your tables, rowstile.toml, the SDK for your stack
7
8
  npx rowstile dev # on each save: check, apply to the development database, test, write the types
package/bin/rowstile.js CHANGED
@@ -64,7 +64,35 @@ function onPath() {
64
64
  return null;
65
65
  }
66
66
 
67
- const python = process.env.ROWSTILE_PYTHON || process.env.ROWFENCE_PYTHON || bundled() || onPath(); // ROWFENCE_PYTHON: the name before the rename
67
+ /** On Windows, a file of the bundled Python whose path is longer than Windows loads (259 characters, unless long
68
+ * paths are turned on): Python then stops with "DLL load failed ... The filename or extension is too long",
69
+ * from inside node_modules. Null when every file is within the limit.
70
+ * @param {string} exe @returns {string | null} */
71
+ function tooLong(exe) {
72
+ if (process.platform !== "win32") return null;
73
+ try {
74
+ const dlls = path.join(path.dirname(fs.realpathSync.native(exe)), "DLLs");
75
+ const longest = fs.readdirSync(dlls).map((f) => path.join(dlls, f)).sort((a, b) => b.length - a.length)[0];
76
+ if (!longest || longest.length <= 259) return null;
77
+ // with long paths turned on, or when only files the command never loads are past the limit, it runs all
78
+ // the same: ask it for the compiled modules the command uses
79
+ const probe = "import unicodedata, ssl, hashlib, socket, select, zlib, decimal";
80
+ return spawnSync(exe, ["-E", "-s", "-c", probe]).status === 0 ? null : longest;
81
+ } catch {
82
+ return null;
83
+ }
84
+ }
85
+
86
+ const own = process.env.ROWSTILE_PYTHON || process.env.ROWFENCE_PYTHON ? null : bundled(); // ROWFENCE_PYTHON: the name before the rename
87
+ const long = own && tooLong(own);
88
+ if (long && !onPath()) {
89
+ console.error(`rowstile: this project's path is too long for Windows to load the Python that came with the package ` +
90
+ `(${long.length} characters to ${path.basename(long)}; Windows loads up to 259). Move the project to a shorter path, ` +
91
+ "or turn long paths on in Windows (LongPathsEnabled), or install Python 3.11 or later: rowstile then runs on that one");
92
+ process.exit(1);
93
+ }
94
+ // a Python on PATH, when the bundled one can't be loaded from here
95
+ const python = process.env.ROWSTILE_PYTHON || process.env.ROWFENCE_PYTHON || (long ? null : own) || onPath();
68
96
  if (!python) {
69
97
  console.error(`rowstile: no Python to run on. The package for this platform (@rowstile/cli-${key}) isn't installed` +
70
98
  (PLATFORMS.includes(key) ? " (optional dependencies turned off?)" : `, and there is none for ${key}`) +
@@ -1,5 +1,6 @@
1
1
  """authzlib: compile a .authz policy file into PostgreSQL (views, closure tables,
2
2
  triggers, row-level security policies and an API for app code)."""
3
+
3
4
  from .devtools import DevMixin
4
5
  from .output import OutputMixin
5
6
  from .parse import Loc, PolicyError, parse_policy
@@ -10,7 +11,8 @@ class Compiler(TestMixin, DevMixin, OutputMixin):
10
11
  """A policy compiled: each part of the output is one of its bases (OutputMixin assembles them)."""
11
12
 
12
13
 
13
- __version__ = "0.1.0-alpha.3" # set with packaging/version.py (the packages copy it); authz.policy_versions records it on each apply
14
+ # set with packaging/version.py (the packages copy it); authz.policy_versions records it on each apply
15
+ __version__ = "0.1.0-alpha.5"
14
16
 
15
17
 
16
18
  def _build() -> str:
@@ -20,6 +22,7 @@ def _build() -> str:
20
22
  return __version__
21
23
  import hashlib
22
24
  import os
25
+
23
26
  here, h = os.path.dirname(os.path.abspath(__file__)), hashlib.sha256()
24
27
  for name in sorted(os.listdir(here)):
25
28
  if name.endswith(".py"):
@@ -177,10 +177,49 @@ CREATE OR REPLACE FUNCTION authz.link_hashes() RETURNS text[] LANGUAGE sql STABL
177
177
  WHERE btrim(x) <> '' $$;"""
178
178
 
179
179
  # Functions each apply recreates (dropped first, whatever their old signature).
180
- GENERATED_FUNCTIONS = ("act_as", "can", "list", "perms", "perms_of", "share", "unshare", "verify", "create_link", "principal",
181
- "create_role", "set_role_permissions", "delete_role", "roles_of", "who", "explain", "list_shares", "shares",
182
- "create_api_key", "list_api_keys", "revoke_api_key", "login_key", "login_jwt", "view_as",
183
- "sync_members", "changes_since", "trim_changes", "trim_audit", "request_access", "pending_requests", "decide_request",
184
- "cancel_request", "break_glass", "start_review", "review_items", "review_decide",
185
- "close_review", "check_invariants", "lint", "connection_check", "explain_rule", "who_among",
186
- "list_links", "revoke_link")
180
+ GENERATED_FUNCTIONS = (
181
+ "act_as",
182
+ "can",
183
+ "list",
184
+ "perms",
185
+ "perms_of",
186
+ "share",
187
+ "unshare",
188
+ "verify",
189
+ "create_link",
190
+ "principal",
191
+ "create_role",
192
+ "set_role_permissions",
193
+ "delete_role",
194
+ "roles_of",
195
+ "who",
196
+ "explain",
197
+ "list_shares",
198
+ "shares",
199
+ "create_api_key",
200
+ "list_api_keys",
201
+ "revoke_api_key",
202
+ "login_key",
203
+ "login_jwt",
204
+ "view_as",
205
+ "sync_members",
206
+ "changes_since",
207
+ "trim_changes",
208
+ "trim_audit",
209
+ "request_access",
210
+ "pending_requests",
211
+ "decide_request",
212
+ "cancel_request",
213
+ "break_glass",
214
+ "start_review",
215
+ "review_items",
216
+ "review_decide",
217
+ "close_review",
218
+ "check_invariants",
219
+ "lint",
220
+ "connection_check",
221
+ "explain_rule",
222
+ "who_among",
223
+ "list_links",
224
+ "revoke_link",
225
+ )