From 7f5cf640002d3cc6bbf67df3be256b72a3476df1 Mon Sep 17 00:00:00 2001 From: Joe Averbukh Date: Mon, 23 Mar 2026 09:35:39 -0700 Subject: [PATCH 1/3] [Auth] Add more extraFields logic --- server/src/instant/model/app_user.clj | 20 +++++++++++++++----- server/test/instant/runtime/routes_test.clj | 20 ++++++++++++++++++++ 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/server/src/instant/model/app_user.clj b/server/src/instant/model/app_user.clj index 1f1380b604..158bd7e157 100644 --- a/server/src/instant/model/app_user.clj +++ b/server/src/instant/model/app_user.clj @@ -43,10 +43,14 @@ extra-fields)))) (defn- assert-create-permission! - [app-id user-data] + [app-id user-data has-extra-fields?] (let [rules (rule-model/get-by-app-id {:app-id app-id}) - program (rule-model/get-program! rules "$users" "create")] - (when program + program (rule-model/get-program! rules + {:etype "$users" + :action "create" + :paths [["$users" "allow" "create"]]})] + (cond + program (let [ctx {:db {:conn-pool (aurora/conn-pool :read)} :app-id app-id :attrs (attr-model/get-by-app-id app-id) @@ -56,7 +60,13 @@ :perms-pass? ["$users" "create"] (cel/eval-program! ctx program {:data user-data - :new-data user-data})))))) + :new-data user-data}))) + + has-extra-fields? + (ex/assert-permitted! + :perms-pass? + ["$users" "create"] + false)))) (defn assert-signup! "Validates extra-fields and checks the $users create permission rule. @@ -66,7 +76,7 @@ (when-not skip-perm-check? (let [id (or (:id params) (random-uuid)) user-data (build-user-data (assoc params :id id))] - (assert-create-permission! app-id user-data)))) + (assert-create-permission! app-id user-data (seq extra-fields))))) (defn create! ([params] diff --git a/server/test/instant/runtime/routes_test.clj b/server/test/instant/runtime/routes_test.clj index a10aff13c0..695c49e8ff 100644 --- a/server/test/instant/runtime/routes_test.clj +++ b/server/test/instant/runtime/routes_test.clj @@ -409,6 +409,8 @@ (test-util/make-attrs app-id [[:$users/username :unique? :index?] [:$users/displayName]]) + (rule-model/put! {:app-id app-id + :code {"$users" {"allow" {"create" "true"}}}}) (testing "new user with extra-fields" (let [code (send-code app {:email "new@test.com"}) @@ -478,6 +480,8 @@ (fn [{app-id :id :as app}] (test-util/make-attrs app-id [[:$users/username]]) + (rule-model/put! {:app-id app-id + :code {"$users" {"allow" {"create" "true"}}}}) (let [guest (sign-in-guest app) _ (is (= "guest" (:type guest))) @@ -498,6 +502,8 @@ (test-util/make-attrs app-id [[:$users/username] [:$users/displayName]]) + (rule-model/put! {:app-id app-id + :code {"$users" {"allow" {"create" "true"}}}}) (let [provider (provider-model/create! {:app-id app-id :provider-name "clerk"})] @@ -632,6 +638,14 @@ :code code})] (is (true? (:created body))))) + (testing "extra-fields without create rule blocks signup" + (let [code (send-code app {:email "norule@test.com"})] + (is (thrown-with-msg? + ExceptionInfo #"status 400" + (verify-body app {:email "norule@test.com" + :code code + :extra-fields {"username" "sneaky"}}))))) + (testing "create rule does not run for existing users" (rule-model/put! {:app-id app-id :code {"$users" {"allow" {"create" "false"}}}}) @@ -693,6 +707,12 @@ (testing "create rule allows guest signup when passing" (rule-model/put! {:app-id app-id :code {"$users" {"allow" {"create" "true"}}}}) + (let [guest (sign-in-guest-runtime app)] + (is (= "guest" (:type guest))))) + + (testing "$default rules do not affect guest signup" + (rule-model/put! {:app-id app-id + :code {"$default" {"allow" {"$default" "false"}}}}) (let [guest (sign-in-guest-runtime app)] (is (= "guest" (:type guest)))))))) From 492439e243f218e726bb56e2de1ba675a98dce64 Mon Sep 17 00:00:00 2001 From: Joe Averbukh Date: Mon, 23 Mar 2026 09:35:54 -0700 Subject: [PATCH 2/3] Add blurb about extraFields perms --- client/www/pages/docs/users.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/www/pages/docs/users.md b/client/www/pages/docs/users.md index 636c44a1db..d150347304 100644 --- a/client/www/pages/docs/users.md +++ b/client/www/pages/docs/users.md @@ -244,6 +244,8 @@ if (created) { } ``` +When using `extraFields`, a `create` rule on `$users` is required. Signup will fail if no rule is defined. This ensures you explicitly opt in to accepting custom fields. A rule of `"true"` allows any values through. See [Signup rules](#signup-rules) for more examples. + ## Signup rules You can write a `create` rule on `$users` to control who can sign up and what fields they can set. This rule runs during the auth signup flow (magic codes, OAuth, guest sign-in) but does not apply to `transact`. From 812bed9df1dc5f504910ebc6ac301b9d70ca60ea Mon Sep 17 00:00:00 2001 From: Joe Averbukh Date: Mon, 23 Mar 2026 09:36:11 -0700 Subject: [PATCH 3/3] Update rules re: extraFields --- client/packages/create-instant-app/template/rules/AGENTS.md | 1 + .../packages/create-instant-app/template/rules/cursor-rules.md | 1 + .../packages/create-instant-app/template/rules/windsurf-rules.md | 1 + client/www/lib/intern/instant-rules.md | 1 + 4 files changed, 4 insertions(+) diff --git a/client/packages/create-instant-app/template/rules/AGENTS.md b/client/packages/create-instant-app/template/rules/AGENTS.md index 10423d933f..ffa0ade57a 100644 --- a/client/packages/create-instant-app/template/rules/AGENTS.md +++ b/client/packages/create-instant-app/template/rules/AGENTS.md @@ -181,6 +181,7 @@ data.ref(someVar + '.members.id') - Can override `view`, `update`, and `create` - Cannot override `delete` - The `create` rule runs during auth signup flows (not via `transact`). Use it to restrict signups or validate `extraFields`. +- `extraFields` require an explicit `create` rule. Without one, signup is blocked to prevent unvalidated writes. ## $files Permissions diff --git a/client/packages/create-instant-app/template/rules/cursor-rules.md b/client/packages/create-instant-app/template/rules/cursor-rules.md index 54299c5e1b..7c3726bfbb 100644 --- a/client/packages/create-instant-app/template/rules/cursor-rules.md +++ b/client/packages/create-instant-app/template/rules/cursor-rules.md @@ -187,6 +187,7 @@ data.ref(someVar + '.members.id') - Can override `view`, `update`, and `create` - Cannot override `delete` - The `create` rule runs during auth signup flows (not via `transact`). Use it to restrict signups or validate `extraFields`. +- `extraFields` require an explicit `create` rule. Without one, signup is blocked to prevent unvalidated writes. ## $files Permissions diff --git a/client/packages/create-instant-app/template/rules/windsurf-rules.md b/client/packages/create-instant-app/template/rules/windsurf-rules.md index 71952cdb9c..04241c1def 100644 --- a/client/packages/create-instant-app/template/rules/windsurf-rules.md +++ b/client/packages/create-instant-app/template/rules/windsurf-rules.md @@ -187,6 +187,7 @@ data.ref(someVar + '.members.id') - Can override `view`, `update`, and `create` - Cannot override `delete` - The `create` rule runs during auth signup flows (not via `transact`). Use it to restrict signups or validate `extraFields`. +- `extraFields` require an explicit `create` rule. Without one, signup is blocked to prevent unvalidated writes. ## $files Permissions diff --git a/client/www/lib/intern/instant-rules.md b/client/www/lib/intern/instant-rules.md index 10423d933f..ffa0ade57a 100644 --- a/client/www/lib/intern/instant-rules.md +++ b/client/www/lib/intern/instant-rules.md @@ -181,6 +181,7 @@ data.ref(someVar + '.members.id') - Can override `view`, `update`, and `create` - Cannot override `delete` - The `create` rule runs during auth signup flows (not via `transact`). Use it to restrict signups or validate `extraFields`. +- `extraFields` require an explicit `create` rule. Without one, signup is blocked to prevent unvalidated writes. ## $files Permissions