Skip to content

ConsoleRPS vs StandaloneRPS API Gap Analysis

ShradhaGupta31 edited this page Oct 6, 2026 · 1 revision

Console RPS APIs vs Standalone RPS — Behavioral Gap Analysis

Tracking issue: device-management-toolkit/console#1261
Blocked PR: #1251 — ci: run MPS and RPS API collections separately
Status: DRAFT for review


1. Executive summary

What happened. Console's RPS APIs have changed over time, but the RPS Postman tests weren't updated with them, so the two have drifted apart. PR #1251 runs the MPS and RPS collections as separate CI steps, so the RPS tests now run in CI and the differences show up as failures.

What fails. 54 of 701 assertions fail on SQLite and PostgreSQL, and 57 on MongoDB:

Cause Rows (Section 2) Failures Fix
Test is out of date: Console changed on purpose 1–3, 7, 9, 10, 18, 21, 37, 39–42, 50, 52, 54 16 Update the test (4.3)
Test is wrong 4–5, 26–27, 47–49 7 Fix the test (4.2)
CIRA is disabled in CI 11–12, 14, 17, 19–20, 28–33, 36, 53 14 Enable CIRA in CI (4.4)
Messages no longer start with Invalid input: 6, 8, 13, 15, 16, 38, 45, 46, 51 9 Reviewers decide: fix Console or update the tests (decision 5)
Console bug: profile PATCH isn't validated 22–25, 34–35, 43–44 8 Fix Console (4.1)
Console bug, MongoDB only: in-use configs can be deleted 55–57 3 Fix Console (4.1)
Total 54 (+3 on MongoDB)

Console bugs found. The two most important:

  • Profile PATCH doesn't validate anything (since v1.40.1), so invalid profiles are saved.
  • On MongoDB, a WiFi / 802.1x / CIRA config can be deleted while a profile still uses it, leaving the profile pointing at nothing.

Section 3 lists more places where MongoDB behaves differently from SQLite/PostgreSQL; the tests don't cover them.


2. Test failures and their causes

Rows 1–54 fail on all three databases (53 assertions + script error #47), in newman order. Rows 55–57 (⚠️ MongoDB only) are the 3 extra failures on MongoDB, which is why it has 57 failures instead of 54. They are numbered last so rows 1–54 keep the same numbers on every database; in the MongoDB newman output they appear between rows 44 and 45.

# Folder / Request Expected → Actual Root cause Class Fix
1–3 Domains / Create duplicate (different case, same name, same suffix) Expected: 400.
Got: 409 Conflict, body unique constraint violation: … UNIQUE constraint failed: index 'lower_name_suffix_idx'.
Each request creates a domain that already exists. RPS answers a duplicate with 400 Unique key violation; Console has deliberately answered 409 Conflict since v1.22.4 (#828), which is the correct HTTP code for a duplicate. The test was written for RPS and never updated. Test stale Expect 409
4–5 Domains / Update Domain Suffix (PATCH) Expected: 200 with the updated domain.
Got: 400 certificate has expired.
Failure 5 ("Result should be equal to payload") follows from 4: the body is an error, so domainSuffix is undefined.
The provisioning certificate in the request expired in Aug 2023. Console checks the certificate again on every update and rejects expired ones; RPS checks it only on create, so the same request passes on RPS. The test also sends version: {{domainVersion}}, which is always empty because Console never returns version; Console ignores it, so it is not the cause. Test bug Replace the certificate with a valid one; remove version from the request
6, 8, 13, 15, 16, 38, 45, 46, 51 Create requests with invalid fields (Profiles, WiFi priority, Wireless 802.1x, 802.1x auth protocol) Expected: exact text Invalid input: Key: 'Profile.Activation' Error:Field validation for 'Activation' failed on the 'required' tag.
Got: the same text without Invalid input: at the start.
Status 400 is correct in all nine.
Console's error handler has a branch that adds Invalid input: to validation errors (the documented format). Since v1.26.3 (#973) that branch is unreachable: NotValidError gained Unwrap(), so the earlier check for a raw validator error matches first and returns the message without the prefix (Section 4.2). Errors from use-case checks still carry the prefix, so Console's messages are now mixed. Row 51 also expects tag matchAuthProtocol, which never existed (Console's tag is authProtocolValidator), so that test needs a change either way. Console bug (since v1.26.3) Reviewer decision (decision 5): add the prefix back in Console, or update the tests
7 Profiles / Create profile6 without activation or amtPassword Expected: message contains both 'AMTPassword' failed on the 'required_if' tag and 'Activation' failed on the 'required' tag.
Got: only the Activation error. Status 400 is correct.
Before #973 both rules were struct tags, so one validation pass reported both. #973 removed required_if from AMTPassword (so PATCH can leave the password out) and moved "password required" into the use case, which runs only after struct validation passes. Here struct validation already fails on activation, so the request is rejected before the password check runs. Test stale Drop the AMTPassword assertion; optionally add a test with activation set and no password
9 Profiles / Create profile6 with weak amtPassword (Intel123) Expected: 'AMTPassword' failed on the 'containsany' tag.
Got: … failed on the 'amtpasswordcomplexity' tag. Status 400 is correct.
Still rejected; only the rule's name changed. #963 replaced the containsany tag with a custom amtpasswordcomplexity validator (RPS's complexity rules). Test stale Update tag name
10 Profiles / Create profile6 acmactivate without mebxPassword Expected: validator text Invalid input: Key: 'Profile.MEBXPassword' … failed on the 'required_if=…' tag.
Got: Invalid input: mebxPassword is required when activation is acmactivate and generateRandomMEBxPassword is false. Status 400 is correct.
Still rejected. #973 moved this rule from a struct tag to a use-case check, which returns a plain-English message. Test stale Update expected text
11, 12, 53 Profiles / Create CIRA Config; same with % in the name; Tenancy / CIRA config with conflicting tenantId Expected: 201 (create) or 400 (invalid input).
Got: 404 CIRA is disabled on this instance.
CI uses .env.example, which sets APP_DISABLE_CIRA=true. With CIRA disabled every CIRA config endpoint returns 404 before reading the request, so these tests never reach the code they are meant to test. Env Enable CIRA in the API-test job
14, 17, 19, 20, 28–33, 36 Profiles / profile testTLS: create, list, update, delete 14 — Expected: 201. Got: 400 CIRA is disabled on this instance.
17, 19, 20 — Expected: 4 profiles. Got: 3.
28–33, 36 — Expected: 200 / 204. Got: 404 Error not found.
Knock-on effect of row 11. ciraconfig3 is never created, so testTLS (which uses it) can't be created either. Every list is one profile short, and every later update or delete of testTLS finds nothing. Cascade None. Fixed by enabling CIRA
18 Profiles / Get All Profiles with $top=ten Expected: Invalid input: strconv.ParseInt: parsing "ten": invalid syntax.
Got: ProfileAPI - BindAndValidate - get: invalid $top parameter: parameter must be a valid integer. Status 400 is correct.
#1180 rewrote OData parameter parsing with its own message, so the text changed. The new message also exposes Console's internal error-wrapping chain (ProfileAPI - BindAndValidate - get:), which isn't meant for API clients. Console bug (minor) + test stale Clean up the message; update the test
21, 50, 52 Create duplicate Profile / Wireless / 802.1x Expected: 400.
Got: 409 unique constraint violation: … profiles.profile_name, profiles.tenant_id (Wireless and 802.1x name their own tables).
Same as rows 1–3. Test stale Expect 409
22–25, 34–35 Profiles / PATCH profile6 with invalid activation activate (22–23), weak amtPassword Intel123 (24–25), or a switch to acmactivate without a MEBx password (34–35) Expected: 400 with a validation error.
Got: 200, and the invalid values are saved (the response shows "activation":"activate").
The second assertion of each pair fails because a 200 body has no error field.
Since #1169 (v1.40.1) the PATCH handler reads the body with plain json.Unmarshal instead of Gin binding, so the struct tags are never checked. The use case merges the change into the stored profile and saves it without validating the result (Section 4.1). Console bug Validate the merged profile → 400
26–27 Profiles / PATCH profile6 ccmactivate, generateRandomPassword:false, no amtPassword (false:missing) Expected: 400.
Got: 200.
Leaving the password out of a PATCH is allowed on purpose (#973: keep the stored password), and RPS also returns 200 here, so the test is wrong. However, Console saves the result without checking that the merged profile still has a password source (neither a stored nor a generated password). Test bug + latent Console bug Expect 200; reject an invalid merged state
37, 39 Integration / POST profile with wifiConfigs and DHCP off (37: dhcpEnabled:false; 39: dhcpEnabled omitted) Expected: 'WiFiConfigs' failed on the 'excluded_if' tag.
Got: … failed on the 'wifidhcp' tag. Status 400 is correct.
Still rejected; only the rule's name changed. f3c3926 replaced excluded_if with a custom wifidhcp validator. Test stale Update tag name
40–42 Integration / same bodies as rows 37 and 38, but sent as PATCH (the request names say "Create"): DHCP off (40), priority 355 (41), priority −1 (42) Expected: 'WiFiConfigs' failed on the 'excluded_if' tag / 'Priority' failed on the 'max' tag / … 'min' tag.
Got: Invalid input: wifiProfiles are not found in the database. Status 400.
PATCH doesn't validate (rows 22–25), so the DHCP and priority rules are never checked. The request is rejected only by accident: the WiFi profile home2 doesn't exist. With an existing WiFi profile, these invalid values would be saved. Test stale + masked Console bug Update tag names; add PATCH validation
43–44 Integration / PATCH wifi-profile with wifiConfigs home/office, dhcpEnabled omitted (stored value is false) Expected: 400.
Got: 200.
Failure 44 follows from 43: a 200 body has no error field.
No PATCH validation, plus data loss: with DHCP off, the update deletes the profile's WiFi links and doesn't re-insert them (internal/usecase/profiles/usecase.go:668-676). The 200 response still lists both WiFi configs because it echoes the request (internal/usecase/profiles/usecase.go:565), so the client doesn't notice they were removed. Console bug Section 4.1
47 Integration / export profile with no domain Expected: the test script runs its checks.
Got: script error ReferenceError: Copy is not defined. The request itself returned 200.
The script's first line is Copy// Get response data: the word "Copy" (probably from a web page's copy button) was pasted into the script. JavaScript reads Copy as an undefined variable, so the script stops before any check runs. Test bug Delete Copy
48–49 Integration / export profile acm with ?domainName=vprodemo.com Expected: 200 with a filename.
Got: 404 No domain found.
The test passes the domain suffix (vprodemo.com) as domainName, but Console and RPS both look domains up by name (vprodemo). On RPS an unknown domain isn't an error: the profile is exported with an empty provisioning certificate and 200, so the test passes there by accident. Console correctly returns 404. Not a cascade of rows 4–5: domain vprodemo was re-created (201) just before this request. Test bug Send domainName=vprodemo
54 Package / Build Package (Path Traversal Version ../../etc) Expected: 400.
Got: 404.
Console treats the version as an unknown release (404), not as invalid input (400). The request is still refused, so there is no path-traversal risk. Test stale (or Console returns 400) Expect 404, or validate the version format first
55–57
⚠️ MongoDB only
Integration / delete Wireless profile office while an AMT profile uses it 55 — Expected: 400 (in use). Got: 204 (deleted).
56: the test reads the error body, but a 204 has none (No data, empty input).
57 — Expected: 204 from the cleanup delete. Got: 404, because the profile is already gone.
On SQLite and PostgreSQL a foreign key blocks the delete. MongoDB has no foreign keys, and Console's use case doesn't check whether the profile is in use, so the AMT profile is left pointing at a deleted WiFi config. DB inconsistency Before deleting, Console's shared code (wificonfigs use case, which runs for every database) checks whether any AMT profile still uses the WiFi profile and returns 400 if so. MongoDB then behaves like SQL; the SQL foreign keys stay as a safety net. Needs a new "is this WiFi profile used?" lookup in both the SQL and MongoDB repositories

3. Multi-DB consistency (Console)

Console must behave the same on every database. This section lists only the places where it doesn't. SQLite and PostgreSQL share the same code and behave the same, so they are one column. Only row 1 is covered by the Postman tests (rows 55–57 in Section 2); the others were found by reading the code.

# What the client does SQLite & PostgreSQL MongoDB Source
1 Delete a WiFi profile that an AMT profile still uses Refused: 400 Deleted: 204. The AMT profile now points to a WiFi profile that doesn't exist Verified live; internal/usecase/nosqldb/mongo/wificonfig.go:156-171
2 Delete an 802.1x config that a profile still uses Refused: 400, but with a generic database error message Deleted: 204 (same broken reference) internal/usecase/sqldb/ieee8021xconfig.go:201-204, internal/usecase/nosqldb/mongo/ieee8021xconfig.go:109-124
3 Delete a CIRA config that a profile still uses Refused: 400 database error Deleted: 204 (same broken reference) internal/usecase/sqldb/ciraconfig.go:192-212
4 Create a profile that names a CIRA / WiFi config that doesn't exist Refused: 400 database error Created: 201. The profile points to nothing internal/app/migrations/20210221023242_migrate_name.up.sql:90-104
5 Use a name with characters other than letters, digits, _ and - (e.g. a space or .) Accepted (only / ? # % are blocked) Create/update: 400 database error; get: 404 internal/usecase/nosqldb/mongo/validate.go:9
6 PATCH a profile with "" for ciraConfigName / ieee8021xProfileName to remove the link Refused: 400. "" is saved as a name, which no config has Accepted: the link is removed internal/usecase/sqldb/profiles.go:262-283, internal/usecase/sqldb/wificonfigs.go:250
7 PATCH a domain to a suffix another domain already uses 409 Conflict 400 database error internal/usecase/nosqldb/mongo/domain.go:162-164
8 List 802.1x configs No fixed order Sorted by name —

SQLite may not always enforce foreign keys (probable, from reading the code; not tested). Console switches foreign-key checks on with PRAGMA foreign_keys=ON, but that setting applies to one database connection only, and Console uses a pool of connections. Requests on the other connections may skip the check, so rows 1–4 could behave like MongoDB on SQLite at random. Fix: put _pragma=foreign_keys(1) in the connection string, so every connection gets it (pkg/db/sql.go:93,103-111).

Rows 1–4 have one cause: SQLite and PostgreSQL rely on database foreign keys to protect references, and MongoDB has none. The fix is a check in Console's shared code (Section 4.1), not a MongoDB-only patch.


4. Fixes to be done

Every failing row in Section 2 and every difference in Section 3 is covered by one of the fixes below, grouped by what has to change. Rows marked Cascade in Section 2 need no fix of their own: they pass once 4.4 is done.

Subsection What changes Rows
4.1 Console defects Console code Sec 2: 6, 8, 13, 15, 16, 18, 22–27, 34–35, 38, 40–46, 51, 55–57 (plus the message text in 1–3, 21, 50, 52)
Sec 3: 1–8
4.2 Test bugs Postman collection: the test itself is wrong Sec 2: 4–5, 26–27, 47, 48–49
4.3 Stale tests Postman collection: Console changed on purpose, the test wasn't updated Sec 2: 1–3, 7, 9, 10, 18, 21, 37, 39–42, 50–52, 54
4.4 CI and environment CI workflow / test environment Sec 2: 11, 12, 53 + cascades 14, 17, 19, 20, 28–33, 36

Some rows need two fixes (e.g. rows 40–42 need Console fix 1 and a test update); they appear in both subsections.

4.1 Console defects

Fixes in Console code. The Client impact column says what existing Console clients will see change.

# Defect Rows What's wrong Fix Client impact
1 Profile PATCH has no validation Sec 2: 22–27, 34–35, 40–44 Since #1169 (001de52, v1.40.1) the PATCH handler reads the body with plain json.Unmarshal, so the struct rules are never checked, and the use case saves the merged profile without validating it. Invalid activation, weak passwords, ACM without MEBx, CIRA+TLS, any tlsMode, and WiFi configs with DHCP off are all saved (the WiFi links are then silently deleted). #973 intentionally allowed PATCH without passwords; #1169 removed all validation by mistake. internal/controller/httpapi/v1/profiles.go:146-182, internal/usecase/profiles/usecase.go:518-568,691-761 Validate the merged profile (struct rules + rules across fields, e.g. a password source must exist) → 400 Invalid PATCH: 200 → 400
2 No reference checks on MongoDB Sec 2: 55–57
Sec 3: 1–4
SQLite/PostgreSQL rely on foreign keys to protect references; MongoDB has none (since e4e33d2 #904, v1.26.0). In-use WiFi / 802.1x / CIRA configs can be deleted, and profiles can point to configs that don't exist Check references in Console's shared use-case code (runs for every database): (1) before deleting a WiFi / 802.1x / CIRA config, refuse it if a profile still uses it (400 or 409, decision 2); (2) before creating or updating a profile, return 400 if a referenced config doesn't exist. SQL foreign keys stay as a safety net. Needs a new "is this config used?" lookup in both the SQL and MongoDB repositories MongoDB: delete in use 204 → 400 or 409; profile with missing config 201 → 400
3 Invalid input: prefix lost Sec 2: 6, 8, 13, 15, 16, 38, 45, 46, 51 #973 (18ba76d, v1.26.3) added Unwrap() to NotValidError; the error handler checks for a raw validator error first, so the branch that adds the prefix is never reached. Use-case errors still have the prefix, so messages are mixed. internal/controller/httpapi/v1/error.go:89-98,281-299 Swap the order of the two checks (restores the documented format). Only if reviewers choose this (decision 5); otherwise update the tests (4.3) Validation message text gains Invalid input:
4 Foreign-key errors shown as database error Sec 3: 2–4 SQL refuses the request correctly, but Console doesn't recognise the foreign-key error for 802.1x and CIRA. internal/usecase/sqldb/ieee8021xconfig.go:201-204, internal/usecase/sqldb/ciraconfig.go:192-212 Map it to a foreign-key error with a clear message (e.g. "802.1x config is in use by a profile") Message text only
5 SQLite may not enforce foreign keys on every connection (probable, from code) Sec 3: note under the table PRAGMA foreign_keys=ON applies to one pooled connection only. pkg/db/sql.go:93,103-111 Put _pragma=foreign_keys(1) in the connection string SQLite: random 204 → always 400
6 MongoDB domain PATCH to a duplicate suffix returns 400 Sec 3: 7 MongoDB Update doesn't recognise the duplicate-key error. internal/usecase/nosqldb/mongo/domain.go:162-164 Map the duplicate-key error → 409, as on SQL MongoDB: 400 → 409
7 "" can't remove a link on SQL Sec 3: 6 SQL saves "" as a config name, which no config has, so the foreign key refuses it. internal/usecase/sqldb/profiles.go:262-283, internal/usecase/sqldb/wificonfigs.go:250 Save "" as NULL in SQL updates, as MongoDB does SQL: 400 → 200
8 MongoDB accepts fewer characters in names Sec 3: 5 MongoDB allows only a-z A-Z 0-9 _ -; SQL allows almost anything. internal/usecase/nosqldb/mongo/validate.go:9 Pick one name rule and check it in shared validation (400 with a clear message) on every database Depends on the rule chosen
9 802.1x list order differs Sec 3: 8 SQL returns no fixed order; MongoDB sorts by name Sort by name on SQL too Order of results
10 OData message exposes the internal error chain Sec 2: 18 ProfileAPI - BindAndValidate - get: … is shown to the client. internal/controller/httpapi/v1/error.go:110-121 Return only the parameter error, e.g. Invalid input: invalid $top parameter: …; then update the test (4.3) Message text only
11 409 messages include raw database text Sec 2: 1–3, 21, 50, 52 (message, not the failure) e.g. UNIQUE constraint failed: index 'lower_name_suffix_idx'. The text differs per database and exposes table and index names Return a fixed message, e.g. "a domain with this name already exists" Message text only

4.2 Test bugs

The test is wrong; fix it in console_rps_apis.postman_collection.json.

Rows Problem Change
4–5 The domain's provisioning certificate expired in Aug 2023; the request also sends version: {{domainVersion}}, which is always empty Replace the certificate with a valid one; remove version from the request
26–27 Expects 400 for a PATCH without a password, but that is allowed on purpose (#973) and RPS also returns 200 Expect 200 (the missing check on the merged profile is Console fix 4.1 #1)
47 The script starts with Copy// Get response data, a pasted copy-button label Delete Copy
48–49 Sends the domain suffix (domainName=vprodemo.com); domains are looked up by name Send domainName=vprodemo
All folders 29 places send {{recordVersion}} (and rows 4–5 send {{domainVersion}}). Console ignores version and never returns one, so these values are always empty. They cause no failures Remove them, once decision 1 confirms Console won't support optimistic concurrency

4.3 Stale tests

Console changed on purpose and the test wasn't updated. Update the expected value.

Rows Test expects Update to
1–3, 21, 50, 52 400 for a duplicate 409 (decision 1)
7 'AMTPassword' failed on the 'required_if' tag in the message Remove that assertion; optionally add a test with activation set and no password, expecting Invalid input: amtPassword is required when generateRandomPassword is false
9 Tag containsany Tag amtpasswordcomplexity
10 Invalid input: Key: 'Profile.MEBXPassword' … 'required_if=…' tag Invalid input: mebxPassword is required when activation is acmactivate and generateRandomMEBxPassword is false
18 Invalid input: strconv.ParseInt: parsing "ten": invalid syntax The new $top message (after Console fix 4.1 #10)
37, 39 Tag excluded_if Tag wifidhcp
40–42 Tags excluded_if / max / min wifidhcp / max / min. They only pass after Console fix 4.1 #1, because they are PATCH requests. Also rename them "Update …", since they are not creates
51 Tag matchAuthProtocol (never existed) Tag authProtocolValidator. Needed whatever is decided about the prefix
54 400 for version ../../etc 404, or keep 400 if Console adds a version-format check
6, 8, 13, 15, 16, 38, 45, 46, 51 Messages starting with Invalid input: Only if reviewers choose "update the tests" (decision 5): remove Invalid input: from the expected text. Otherwise no change: Console fix 4.1 #3 makes them pass

Tests to add (missing from the collection): port the RPS CIRA folder (with the 409 and CIRA name case-sensitivity decisions applied); re-add "Get Domain — domain name case insensitive".

4.4 CI and environment

  1. Keep #1251's separate newman steps. They are required: the current single newman run <mps> run <rps> form never runs the RPS collection.
  2. Set APP_DISABLE_CIRA=false for the API-test jobs. Fixes rows 11, 12 and 53, and with them the cascade rows 14, 17, 19, 20, 28–33 and 36.
  3. Add an SQLite job (CI only runs PostgreSQL and MongoDB today).
  4. Remove the Package folder's dependency on the live GitHub API (mock it or use RPC_LOCAL_DIR). Once GitHub's rate limit is hit, 9 more assertions fail.

5. Decisions needed from reviewers

  1. Should Console keep behaving differently from RPS in the areas below, or be changed to match RPS? If Console keeps its behaviour, the Postman tests that expect RPS's behaviour must be updated (Section 4.3). If Console changes, existing clients that depend on its current behaviour may break.

    Area RPS Console (keep) Since
    Duplicate create 400 Unique key violation 409 476f798 #828, v1.22.4 (Mar 2026); in OpenAPI since v1.24.2 (#915)
    Validation error body {errors:[{msg,path,…}]} (all errors) {error,message} (first failing stage only) v1.0.0
    Optimistic concurrency version required on PATCH; 409/412 on mismatch; ETag; 304 on list Not supported; version never returned v1.0.0
    PATCH semantics Domains/CIRA/Wireless/802.1x: merge. Profiles: omitted CIRA/TLS/802.1x fields cleared Domains/CIRA/Wireless/802.1x: full replace (all required fields). Profiles: merge, omitted fields kept —
    Domain cert checks CN/suffix match, chain, key size, AMT OID; not re-checked on PATCH base64, PKCS12/password, expiry only; re-checked on PATCH —
    OData limits $top ≤ 9999999999 $top ≤ 500, $skip ≤ 100000 a493e12 #1180, v1.40.1
    CIRA Always on Behind APP_DISABLE_CIRA (default true) → 404 —
    Health / Version /api/v1/admin/health, /api/v1/admin/version /healthz (no DB check), /version (GitHub latest) —
    Proxy configs /api/v1/admin/proxy Not supported (the Postman folder was dropped) —
    802.1x on profile create: exists + wired; update: exists exists + wired on both —
    Multi-tenancy none x-tenant-id scoping (Tenancy folder) —

    Three of these need an explicit answer:

    • Duplicates: is 409 the accepted contract? (Recommended: yes. It has been Console's behaviour for ~24 releases.)
    • PATCH: keep full replace for Domains/CIRA/Wireless/802.1x, or adopt RPS's merge?
    • Optimistic concurrency (version/ETag): on the roadmap, or permanently out of scope?
  2. When a client deletes a WiFi / 802.1x / CIRA config that a profile still uses, should Console return 400 or 409? Today RPS returns 400, Console on SQLite/PostgreSQL returns 400, and Console on MongoDB deletes it (204). Console fix 4.1 #2 adds the check for every database, so it needs one status code. 400 matches RPS and what SQL clients see today; 409 (Conflict) matches what Console returns for duplicates, but changes the response SQL clients see today.

  3. Should CIRA config names be case-sensitive? RPS treats CiraConfig1 and ciraconfig1 as the same name (stored as citext); Console treats them as different names on every database. If Console changes to match RPS, existing Console databases may already hold names that differ only in case, and those would then clash. If Console keeps exact matching, the RPS CIRA tests being ported (Section 4.3) must be changed to expect it.

  4. Should the Console fixes in Section 4.1 go in separate PRs, or into #1251? #1251 only changes how CI runs the Postman collections. Separate PRs keep each change small and follow Console's "one PR fixes one problem" rule, but #1251 can't pass CI until the fixes it depends on are merged. Putting them into #1251 unblocks it in one step, but makes it a large PR that mixes CI, test and Console code changes.

  5. Should validation error messages start with Invalid input: ? Console's documented format starts every validation message with it. Since v1.26.3, messages from struct validation don't (4.1 #3), while messages from use-case checks still do. 9 failures depend on the answer. If the prefix is added back, Console code changes and the 9 tests pass as they are; clients that read the messages today see different text. If it isn't, the 9 tests are updated (Section 4.3) and the documented format no longer matches Console.

Clone this wiki locally