Skip to content

Conversation

@robert-chiniquy
Copy link
Collaborator

@robert-chiniquy robert-chiniquy commented Jan 22, 2026

Summary by CodeRabbit

  • New Features

    • Added subject.manager_id for direct manager ID lookups.
  • Documentation

    • Major CEL documentation expansion: examples, workflows, troubleshooting, functions, environments, connector guidance, and navigation updates.
    • New Approver selection patterns, production guidance, safe-access patterns (has()/fallbacks), and explicit warnings for empty manager/lookup results.
  • Bug Fixes / Guidance

    • Clarified failure modes and recommended safe fallbacks to avoid silent skips.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 22, 2026

📝 Walkthrough

Walkthrough

Expanded CEL expressions documentation and added a large RAP/connector knowledge base. Introduced subject.manager_id, explicit safety/warning notes and approver-fallback patterns in examples, new workflow and troubleshooting guides, many RAP connector/SDK guidance files, and navigation updates. All changes are documentation-only.

Changes

Cohort / File(s) Summary
Core expressions & examples
product/admin/expressions.mdx, product/admin/expressions-examples.mdx, product/admin/expressions-reference.mdx, product/admin/expressions-workflows.mdx, product/admin/expressions-troubleshooting.mdx
Added subject.manager_id; clarified return types and terminology; inserted DANGER/SAFE/SILENT FALSE annotations; new Approver selection patterns and fallback examples; workflow template/ctx guidance; troubleshooting (compile vs runtime).
Navigation / docs index
docs.json
Added new CEL expressions pages to Platform and Developer navigation groups and linked new docs.
RAP Connector CEL & functions
product/admin/rap/*, product/admin/rap/index.md, product/admin/rap/functions-*.md, product/admin/rap/overview-intro.md, product/admin/rap/patterns-common.md, product/admin/rap/connectors-bcel.md
New RAP knowledge base covering Connector CEL vs Policy CEL, directory functions (GetManagers, FindByEmail, GetByID, etc.), string/time/IP/user helpers, safe-access patterns, environment-specific patterns (approvers, workflows, triggers, dynamic groups, provisioning, push filters), and null-handling semantics.
RAP: connector developer guides & recipes
rap/* (e.g., rap/ref-sdk.md, rap/build-*, rap/recipes-*, rap/ref-*, rap/concepts-*.md, rap/meta-*.md)
Large set of new connector developer docs: SDK/reference interfaces and types, build/setup, syncer patterns, pagination, provisioning, publishing, auth recipes, caching, error handling, testing, meta-connector specs (HTTP/SQL), debugging, and ops guidance.
Miscellaneous docs / metadata
developer/build-connector.mdx, assorted MDX/MD files
Minor editorial notes, LLM assistant comment blocks, date/metadata tweaks, and inline clarifications added across existing docs.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I nibble warnings, tuck fallbacks tight,

I hop through docs by soft lamplight.
Manager IDs and has() now sing,
Safe paths sprout from every wing.
Hooray—expressions bloom, take flight!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Tentatively add more CEL docs' is vague and uses non-descriptive language. It does not clearly convey the specific nature or scope of the documentation additions beyond a generic reference to 'more CEL docs'. Replace with a more specific title that describes the primary documentation additions, such as 'Add comprehensive CEL documentation suite with examples, troubleshooting, and Baton connector patterns' or similar.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@product/admin/expressions-examples.mdx`:
- Around line 61-63: Update the example expression to use the snake_case manager
field name used in the docs: replace occurrences of subject.managerId with
subject.manager_id in the array expression that calls
c1.directory.users.v1.GetByID (i.e., the line with
[c1.directory.users.v1.GetByID(c1.directory.users.v1.GetByID(subject.managerId).managerId),
c1.directory.users.v1.GetByID(subject.managerId)] should instead reference
subject.manager_id and the nested .manager_id) so both the inner and outer
GetByID calls use subject.manager_id consistently.
🧹 Nitpick comments (1)
product/admin/expressions-reference.mdx (1)

45-57: Clarify appOwners provenance in the warning example.
Line 52 introduces appOwners without explaining where it comes from. A short note here would prevent confusion for first‑time readers.

✅ Suggested doc tweak
 </Warning>
 
+<Info>
+`appOwners` is available in policy step approver expressions and returns the app owners list.
+</Info>

Comment on lines 61 to 63
// Route to user's manager AND skip-level manager
// DANGER: Fails if managerId is empty
[c1.directory.users.v1.GetByID(c1.directory.users.v1.GetByID(subject.managerId).managerId), c1.directory.users.v1.GetByID(subject.managerId)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Find and read the mdx file
fd -t f "expressions-examples.mdx"

Repository: ConductorOne/docs

Length of output: 99


🏁 Script executed:

# If found, read the file around lines 61-63
cat -n product/admin/expressions-examples.mdx | sed -n '50,75p'

Repository: ConductorOne/docs

Length of output: 1232


🏁 Script executed:

# Search for references to manager_id and managerId in the codebase
rg -i "manager_id|managerId" --max-count 20

Repository: ConductorOne/docs

Length of output: 999


🏁 Script executed:

# Search for reference documentation or schema files
fd -t f -e "md" -e "mdx" -e "json" | xargs rg -l "subject\.manager" 2>/dev/null | head -10

Repository: ConductorOne/docs

Length of output: 139


Correct manager ID field name to match reference documentation.

Lines 61-63 use subject.managerId (camelCase), but the official reference documentation specifies subject.manager_id (snake_case). The expressions-workflows.mdx and expressions-reference.mdx files consistently use the snake_case convention. Update the example to use the correct field name to prevent copy-paste errors.

Fix
-c1.directory.users.v1.GetByID(c1.directory.users.v1.GetByID(subject.managerId).managerId), c1.directory.users.v1.GetByID(subject.managerId)
+c1.directory.users.v1.GetByID(c1.directory.users.v1.GetByID(subject.manager_id).manager_id), c1.directory.users.v1.GetByID(subject.manager_id)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Route to user's manager AND skip-level manager
// DANGER: Fails if managerId is empty
[c1.directory.users.v1.GetByID(c1.directory.users.v1.GetByID(subject.managerId).managerId), c1.directory.users.v1.GetByID(subject.managerId)]
// Route to user's manager AND skip-level manager
// DANGER: Fails if manager_id is empty
[c1.directory.users.v1.GetByID(c1.directory.users.v1.GetByID(subject.manager_id).manager_id), c1.directory.users.v1.GetByID(subject.manager_id)]
🤖 Prompt for AI Agents
In `@product/admin/expressions-examples.mdx` around lines 61 - 63, Update the
example expression to use the snake_case manager field name used in the docs:
replace occurrences of subject.managerId with subject.manager_id in the array
expression that calls c1.directory.users.v1.GetByID (i.e., the line with
[c1.directory.users.v1.GetByID(c1.directory.users.v1.GetByID(subject.managerId).managerId),
c1.directory.users.v1.GetByID(subject.managerId)] should instead reference
subject.manager_id and the nested .manager_id) so both the inner and outer
GetByID calls use subject.manager_id consistently.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
product/admin/expressions.mdx (1)

83-105: Align alt text with the new “Policy conditions” term.

The image alt text at Line 86 still says “policy conditionals,” while the section now uses “Policy conditions” (Line 89). Please update the alt text for consistency.

🔧 Suggested fix
-<img src="/images/product/assets/conditional-policies.png" alt="A policy's details view, showing the policy conditionals and expressions."/>
+<img src="/images/product/assets/conditional-policies.png" alt="A policy's details view, showing the policy conditions and expressions."/>

Based on learnings, keep terminology consistent.

🤖 Fix all issues with AI agents
In `@product/admin/expressions.mdx`:
- Line 53: Update internal links that use root‑relative paths to relative paths
local to this MDX file; specifically replace
"/product/admin/expressions-reference" (the link text "[expressions reference]")
with a relative link (e.g., "./expressions-reference") and apply the same change
to the other internal links referenced around the occurrences at lines 74, 115
and 139-145 so they point to sibling or parent MDX files using relative paths
instead of starting with a leading slash.
- Around line 4-5: Update the frontmatter metadata keys 'og:description' and
'description' in expressions.mdx to use a neutral, technical phrasing instead of
promotional language like "powerful rules" — for example describe that users
"write Common Expression Language (CEL) expressions to define rules for
ConductorOne policies and groups" or similar concise, neutral wording; ensure
both 'og:description' and 'description' are changed to the same neutral sentence
to keep metadata consistent.
- Line 119: Update the heading text "Campaigns - Precisely target access
reviews" to sentence case by lowercasing non-proper words after the first word
(e.g., change to "Campaigns - Precisely target access reviews"), ensuring only
the first word and any proper nouns remain capitalized in the heading.
- Line 13: Update the paragraph in product/admin/expressions.mdx to add inline
citations and clarify Kubernetes usage: include links/references to cel.dev and
https://github.com/google/cel-spec for CEL origin, add citations to Firebase
Rules and Google Cloud IAM Conditions docs to support those usage claims, and
replace "Kubernetes admission webhooks" with a precise phrase such as
"Kubernetes ValidatingAdmissionPolicy (built-in admission control)" noting
webhooks are separate; ensure the ConductorOne extension sentence remains but
add a final "Sources" note or inline footnotes listing these URLs.

In `@product/admin/rap/connectors-bcel.md`:
- Around line 49-50: The display_name example uses a CEL expression for
cel:item.firstName but misses the cel: prefix on item.lastName so the second
part won't be evaluated; update the display_name value to use cel:item.lastName
(i.e., make both operands cel:item.firstName and cel:item.lastName concatenated
with " ") so the entire expression is treated as CEL.

In `@product/admin/rap/env-dynamic-groups.md`:
- Around line 55-59: The example CEL expression uses the wrong status constant:
replace the literal USER_STATUS_ENABLED with the proper enum constant
UserStatus.ENABLED in the expression that checks subject.status (keep the
human-only check subject.type == UserType.HUMAN as-is); update any other
occurrences of USER_STATUS_ENABLED (e.g., the other example that uses
subject.status) to UserStatus.ENABLED so the examples use the correct symbol.

In `@product/admin/rap/env-workflow.md`:
- Around line 26-28: The fenced code block containing the template snippet
"Hello {{ ctx.trigger.user.display_name }}!" is missing a language identifier
(MD040); update the triple-backtick fence to include a language like "text" so
it reads ```text before the snippet and ``` after, ensuring the code block in
env-workflow.md (the template snippet with ctx.trigger.user.display_name) is
properly annotated.
🧹 Nitpick comments (6)
product/admin/rap/env-dynamic-groups.md (2)

30-39: Add null‑safety guards for optional fields in examples.

subject.job_title and subject.email may be unset in some directories, which can make these examples error at runtime. Consider showing has() checks to model safe usage.

💡 Suggested doc tweak
-// Simple contains
-subject.job_title.contains("Manager")
+// Simple contains (safe)
+has(subject.job_title) && subject.job_title.contains("Manager")

-// Case-insensitive
-subject.job_title.lowerAscii().contains("manager")
+// Case-insensitive (safe)
+has(subject.job_title) && subject.job_title.lowerAscii().contains("manager")

-// Multiple patterns
-subject.job_title.contains("Director") || subject.job_title.contains("VP")
+// Multiple patterns (safe)
+has(subject.job_title) && (subject.job_title.contains("Director") || subject.job_title.contains("VP"))

-// Internal employees
-subject.email.endsWith("@company.com")
+// Internal employees (safe)
+has(subject.email) && subject.email.endsWith("@company.com")

-// Exclude contractors
-!subject.email.endsWith("@contractor.company.com")
+// Exclude contractors (safe)
+has(subject.email) && !subject.email.endsWith("@contractor.company.com")

Also applies to: 43-49


65-66: Align has() usage with bracket‑notation keys.

The example checks has(subject.profile.costCenter) but then reads subject.profile["costCenter"]. For map-style profile data, it’s clearer to use the same access form for both the existence check and the read.

💡 Suggested doc tweak
-// Cost center from profile
-has(subject.profile.costCenter) && subject.profile["costCenter"] == "CC-123"
+// Cost center from profile
+"costCenter" in subject.profile && subject.profile["costCenter"] == "CC-123"
product/admin/rap/env-push-filter.md (1)

42-48: Guard profile lookups with has()/in in examples.

subject.profile['location'] / subject.profile['department'] will throw if the key is missing; this conflicts with the safety guidance below. Consider adding a safe-access variant in the example.

♻️ Proposed edit
-// Users in specific location
-subject.profile['location'] == 'San Francisco'
+// Users in specific location (safe)
+has(subject.profile['location']) && subject.profile['location'] == 'San Francisco'

-// Users with specific cost center
-subject.profile['department'] == 'Engineering'
+// Users with specific cost center (safe)
+has(subject.profile['department']) && subject.profile['department'] == 'Engineering'
product/admin/rap/patterns-common.md (1)

13-15: Align has() with map-style profile access.

has(subject.profile.costCenter) implies dot-access, but the example then uses map indexing; for arbitrary profile keys, map access is clearer and consistent.

♻️ Proposed edit
-// For profile fields (always use has)
-has(subject.profile.costCenter) && subject.profile["costCenter"] == "CC-123"
+// For profile fields (always use has)
+has(subject.profile["costCenter"]) && subject.profile["costCenter"] == "CC-123"
product/admin/rap/functions-directory.md (1)

109-115: Provide a safe skip-level example to avoid runtime errors.

The example accesses [0] without a guard; users often copy/paste examples. Consider showing a size check inline.

♻️ Proposed edit
-c1.directory.users.v1.GetManagers(
-  c1.directory.users.v1.GetManagers(subject)[0]
-)
+size(c1.directory.users.v1.GetManagers(subject)) > 0
+  ? c1.directory.users.v1.GetManagers(
+      c1.directory.users.v1.GetManagers(subject)[0]
+    )
+  : []
product/admin/rap/env-user-attribute.md (1)

30-33: Guard email split to avoid out-of-bounds access.

split("@")[1] will fail if the email is missing @. Consider a safe pattern in the example.

♻️ Proposed edit
-// Return email domain
-subject.email.split("@")[1]
+// Return email domain (safe)
+subject.email.split("@").size() > 1
+  ? subject.email.split("@")[1]
+  : ""

Comment on lines +4 to +5
og:description: Write Common Expression Language (CEL) expressions to create powerful rules for ConductorOne policies and groups.
description: Write Common Expression Language (CEL) expressions to create powerful rules for ConductorOne policies and groups.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Tone: make the descriptions neutral.

“Powerful rules” reads promotional. Consider neutral phrasing in the metadata descriptions.

💡 Suggested wording
-og:description: Write Common Expression Language (CEL) expressions to create powerful rules for ConductorOne policies and groups.
-description: Write Common Expression Language (CEL) expressions to create powerful rules for ConductorOne policies and groups.
+og:description: Write Common Expression Language (CEL) expressions to define rules for ConductorOne policies and groups.
+description: Write Common Expression Language (CEL) expressions to define rules for ConductorOne policies and groups.

Based on learnings, keep the tone technical and non‑promotional.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
og:description: Write Common Expression Language (CEL) expressions to create powerful rules for ConductorOne policies and groups.
description: Write Common Expression Language (CEL) expressions to create powerful rules for ConductorOne policies and groups.
og:description: Write Common Expression Language (CEL) expressions to define rules for ConductorOne policies and groups.
description: Write Common Expression Language (CEL) expressions to define rules for ConductorOne policies and groups.
🤖 Prompt for AI Agents
In `@product/admin/expressions.mdx` around lines 4 - 5, Update the frontmatter
metadata keys 'og:description' and 'description' in expressions.mdx to use a
neutral, technical phrasing instead of promotional language like "powerful
rules" — for example describe that users "write Common Expression Language (CEL)
expressions to define rules for ConductorOne policies and groups" or similar
concise, neutral wording; ensure both 'og:description' and 'description' are
changed to the same neutral sentence to keep metadata consistent.


CEL (Common Expression Language) expressions are powerful, flexible rules that let you automate decision-making across ConductorOne. Instead of manually configuring each policy, group, or automation, you can write expressions that automatically adapt to your organization's unique needs.

CEL is an open-source expression language created by Google. It's the same technology behind Firebase Rules, Google Cloud IAM conditions, and Kubernetes admission webhooks. ConductorOne extends standard CEL with custom functions for directory lookups, user queries, and access management.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

CEL Common Expression Language Google official documentation

💡 Result:

  • CEL project homepage + docs (overview, get started, language definition): cel.dev [1]
  • Official CEL specification & binary representation (google/cel-spec): GitHub repo (spec, AST/binary format, language definition links) [2]
  • Official Go implementation docs (google/cel-go): pkg.go.dev module docs/README (usage + pointers to language resources) [3]
  • Google Cloud product docs that use CEL (dialects/usage examples vary by product):
    • Service Extensions CEL matcher language reference [4]
    • Eventarc “Use CEL” guide [5]
    • Certificate Authority Service “Use CEL” guide [6]

Sources: [1]–[6]


🌐 Web query:

CEL Firebase Rules Kubernetes admission webhooks Google Cloud IAM

💡 Result:

All four terms connect through policy-as-code using CEL (Common Expression Language), but in different products and at different enforcement points:

  • Firebase Security Rules (Firestore / Cloud Storage): Rules are based on CEL (plus Firebase-specific match / allow structure) to decide whether a request is authorized. [1]
  • Google Cloud IAM Conditions: IAM lets you attach conditional expressions written in a subset of CEL to role bindings; the binding only applies when the CEL condition evaluates to true. [2]
  • Kubernetes (in the API server): Kubernetes embeds CEL directly in the API server for declarative validation / policy so decisions don’t require an external service. [3]
  • Kubernetes admission webhooks vs CEL-based admission: For admission control, Kubernetes documents that webhooks are appropriate for complex logic (including calling external APIs), while built-in CEL-based admission policies are recommended “when possible” to avoid webhook operational overhead. [4]

In short: Firebase Rules, GCP IAM Conditions, and Kubernetes ValidatingAdmissionPolicy / CEL validation all use CEL-style expressions for authorization/validation, while Kubernetes admission webhooks are the (more flexible but operationally heavier) out-of-process alternative. [1][2][3][4]

Sources
[1] Firebase Security Rules language (Firestore/Storage rules based on CEL)
[2] Google Cloud IAM Conditions overview (CEL subset for conditional bindings)
[3] Kubernetes: Common Expression Language in Kubernetes
[4] Kubernetes: Admission webhook good practices (webhooks vs CEL-based admission policies)


🌐 Web query:

CEL open-source expression language Google github documentation

💡 Result:

Google’s CEL (Common Expression Language) is open-source and documented primarily here:

  • Project website (overview + docs entry points): CEL homepage at cel.dev (cel.dev)
  • Language spec + conformance tests (canonical documentation): google/cel-spec on GitHub (github.com)
  • Reference implementations (GitHub):

If you tell me your target language (Go/Java/JS/Python/etc.), I can point to the most relevant “getting started” and API docs within that repo.

Citations:


Add citations for CEL claims and clarify Kubernetes usage.

The statements about CEL's origin and usage are factually accurate but lack citations required by the coding guidelines. Additionally, the Kubernetes reference needs clarification:

  • CEL origin and implementations are documented at cel.dev and github.com/google/cel-spec (GitHub)
  • Firebase Rules and Google Cloud IAM Conditions documentation both confirm CEL usage
  • CEL is used in Kubernetes ValidatingAdmissionPolicy for built-in admission control, not in admission webhooks (webhooks are a separate, out-of-process alternative)

Add inline citations or a sources note to the documentation.

🤖 Prompt for AI Agents
In `@product/admin/expressions.mdx` at line 13, Update the paragraph in
product/admin/expressions.mdx to add inline citations and clarify Kubernetes
usage: include links/references to cel.dev and
https://github.com/google/cel-spec for CEL origin, add citations to Firebase
Rules and Google Cloud IAM Conditions docs to support those usage claims, and
replace "Kubernetes admission webhooks" with a precise phrase such as
"Kubernetes ValidatingAdmissionPolicy (built-in admission control)" noting
webhooks are separate; ensure the ConductorOne extension sentence remains but
add a final "Sources" note or inline footnotes listing these URLs.

| **User attribute mapping** | text or list of text | Derive user attributes from existing data |

<Info>
Each context provides different variables. For example, `subject` is available in most contexts, but `ctx.trigger` is only available in automations. See the [expressions reference](/product/admin/expressions-reference) for details.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use relative paths for internal links.

These links use root‑relative paths. Please switch to paths relative to this MDX file (and apply the same pattern to other internal links in this doc, e.g., Line 74 and Line 115).

🔧 Example updates
- - **[Expressions reference](/product/admin/expressions-reference)** - Complete reference for all available objects, functions, and their usage
+ - **[Expressions reference](./expressions-reference)** - Complete reference for all available objects, functions, and their usage
- - **[Examples and patterns](/product/admin/expressions-examples)** - Practical examples, common patterns, and real-world use cases
+ - **[Examples and patterns](./expressions-examples)** - Practical examples, common patterns, and real-world use cases
- - **[Workflow expressions](/product/admin/expressions-workflows)** - Pass data between automation steps using the ctx object
+ - **[Workflow expressions](./expressions-workflows)** - Pass data between automation steps using the ctx object
- - **[Troubleshooting](/product/admin/expressions-troubleshooting)** - Debug common errors and understand failure modes
+ - **[Troubleshooting](./expressions-troubleshooting)** - Debug common errors and understand failure modes

As per coding guidelines, use relative paths for internal links.

Also applies to: 139-145

🤖 Prompt for AI Agents
In `@product/admin/expressions.mdx` at line 53, Update internal links that use
root‑relative paths to relative paths local to this MDX file; specifically
replace "/product/admin/expressions-reference" (the link text "[expressions
reference]") with a relative link (e.g., "./expressions-reference") and apply
the same change to the other internal links referenced around the occurrences at
lines 74, 115 and 139-145 so they point to sibling or parent MDX files using
relative paths instead of starting with a leading slash.

*Example: Automatically revoke access for users who haven't logged in for 45 days, but only for non-critical applications.*

### Campaigns - Precisely target access reviews
### Campaigns - Precisely target access reviews
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use sentence case in the Campaigns heading.

✏️ Suggested fix
-### Campaigns - Precisely target access reviews
+### Campaigns - precisely target access reviews

As per coding guidelines, keep headings in sentence case.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
### Campaigns - Precisely target access reviews
### Campaigns - precisely target access reviews
🤖 Prompt for AI Agents
In `@product/admin/expressions.mdx` at line 119, Update the heading text
"Campaigns - Precisely target access reviews" to sentence case by lowercasing
non-proper words after the first word (e.g., change to "Campaigns - Precisely
target access reviews"), ensuring only the first word and any proper nouns
remain capitalized in the heading.

Comment on lines +49 to +50
id: cel:item.id
display_name: cel:item.firstName + " " + item.lastName
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix missing cel: prefix in example.

item.lastName is missing the cel: prefix, so it won’t be evaluated as a CEL expression.

🛠️ Proposed fix
-          display_name: cel:item.firstName + " " + item.lastName
+          display_name: cel:item.firstName + " " + item.lastName
🤖 Prompt for AI Agents
In `@product/admin/rap/connectors-bcel.md` around lines 49 - 50, The display_name
example uses a CEL expression for cel:item.firstName but misses the cel: prefix
on item.lastName so the second part won't be evaluated; update the display_name
value to use cel:item.lastName (i.e., make both operands cel:item.firstName and
cel:item.lastName concatenated with " ") so the entire expression is treated as
CEL.

Comment on lines +55 to +59
subject.status == USER_STATUS_ENABLED
// Human users only (not service accounts)
subject.type == UserType.HUMAN
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for USER_STATUS_ENABLED and UserType.HUMAN in markdown files
echo "=== Searching in markdown files ==="
rg -n 'USER_STATUS_ENABLED|UserType\.HUMAN' -g '*.{md,mdx}' || echo "No matches in markdown"

# Also search in code files to understand the actual constant definitions
echo -e "\n=== Searching for USER_STATUS_ENABLED in all files ==="
rg -n 'USER_STATUS_ENABLED' --max-count=10

echo -e "\n=== Searching for UserType in all files ==="
rg -n 'UserType' --max-count=10

# Look for CEL-related files and dynamic group evaluation
echo -e "\n=== Looking for CEL/dynamic-group related files ==="
fd -e 'go|java|proto' | grep -i 'cel\|dynamic.*group\|evaluator' | head -20

Repository: ConductorOne/docs

Length of output: 2515


🏁 Script executed:

#!/bin/bash
# Look for subject.status documentation and valid status constants
echo "=== Searching for subject.status in expressions reference ==="
rg -A 5 -B 5 'subject\.status' product/admin/expressions-reference.mdx | head -100

echo -e "\n=== Searching for status constants and enums ==="
rg -n 'status.*enum|status.*constant|STATUS_' product/admin/expressions-reference.mdx | head -30

# Check what the expressions-reference file contains for status values
echo -e "\n=== Looking for status values/constants definition ==="
rg -A 10 'subject\.status' product/admin/expressions-reference.mdx | grep -i 'value\|constant\|enum' | head -20

Repository: ConductorOne/docs

Length of output: 2186


Update status constant in code examples.

UserType.HUMAN is correct, but USER_STATUS_ENABLED should be UserStatus.ENABLED per the CEL expressions reference. Update line 55 to use subject.status == UserStatus.ENABLED.

This same incorrect constant also appears in product/admin/rap/patterns-common.md:127 and should be corrected there as well.

🤖 Prompt for AI Agents
In `@product/admin/rap/env-dynamic-groups.md` around lines 55 - 59, The example
CEL expression uses the wrong status constant: replace the literal
USER_STATUS_ENABLED with the proper enum constant UserStatus.ENABLED in the
expression that checks subject.status (keep the human-only check subject.type ==
UserType.HUMAN as-is); update any other occurrences of USER_STATUS_ENABLED
(e.g., the other example that uses subject.status) to UserStatus.ENABLED so the
examples use the correct symbol.

Comment on lines +26 to +28
```
Hello {{ ctx.trigger.user.display_name }}!
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add a language to the fenced code block.

The template snippet is missing a language identifier (markdownlint MD040).

🛠️ Proposed fix
-```
+```text
 Hello {{ ctx.trigger.user.display_name }}!
</details>

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

26-26: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
In `@product/admin/rap/env-workflow.md` around lines 26 - 28, The fenced code
block containing the template snippet "Hello {{ ctx.trigger.user.display_name
}}!" is missing a language identifier (MD040); update the triple-backtick fence
to include a language like "text" so it reads ```text before the snippet and ```
after, ensuring the code block in env-workflow.md (the template snippet with
ctx.trigger.user.display_name) is properly annotated.

27 skill files in rap/ for Retrieval Augmented Prompt usage.
Breadcrumb in developer/build-connector.mdx using MDX comment syntax.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@rap/build-setup.md`:
- Around line 28-37: The go.mod snippet uses an invalid version specifier
"v0.2.x" for the require line (github.com/conductorone/baton-sdk v0.2.x); update
the require entry to a concrete semantic version such as "v0.2.0" or replace the
line with guidance to fetch the module dynamically using `go get` (e.g.,
instruct developers to run `go get github.com/conductorone/baton-sdk@latest`) so
the module declaration (module github.com/conductorone/baton-myservice and the
require block) contains a valid Go module version.

In `@rap/recipes-auth.md`:
- Around line 50-66: The code calls google.JWTConfigFromJSON inside
NewGoogleClient but the google package is not imported, causing a compile error;
fix by adding the required import for the google package (the oauth2/jwt
provider) to the import block so JWTConfigFromJSON resolves, then ensure
NewGoogleClient still sets config.Subject and returns admin.NewService with
option.WithHTTPClient(config.Client(ctx)).

In `@rap/ref-c1api.md`:
- Around line 113-127: The fenced diagram block for the task lifecycle in
rap/ref-c1api.md is missing a language tag, triggering markdownlint MD040;
update the opening fence for that diagram to include a language (e.g., change
the opening ``` to ```text) so the diagram block is fenced as ```text ... ```
and passes the linter while preserving the diagram content and closing fence.
- Around line 9-17: The fenced architecture diagram block in rap/ref-c1api.md is
missing a language specifier which triggers Markdownlint MD040; update the
opening fence for the diagram (the triple-backtick that begins the diagram
block) to include a language token (e.g., text) so it reads ```text and ensure
the closing triple-backtick remains; locate the diagram block that contains the
ASCII box drawing (the ConductorOne Platform / Connector (Daemon Mode) diagram)
and change only the opening fence to add the language.
🧹 Nitpick comments (10)
rap/ref-faq.md (1)

54-58: Add language specification to fenced code block.

The code block is missing a language identifier. Consider adding text or plaintext for consistency and to silence linter warnings.

📝 Proposed fix
-```
+```text
 --client-id provided?
   No  --> One-shot
   Yes --> Daemon
rap/community.md (1)

91-99: Add language specification to fenced code block.

The code block would benefit from a language identifier for consistency.

📝 Proposed fix
-```
+```text
 1. Fork repo
 2. Create branch
 3. Make changes
 4. Run build/lint/test
 5. Submit PR
 6. Address feedback
 7. Merge
rap/concepts-sync.md (2)

11-26: Add language specification to fenced code block.

Consider adding a language identifier for the text diagram.

📝 Proposed fix
-```
+```text
 Stage 1: ResourceType()
   SDK learns what resource types exist (user, group, role)
 
 Stage 2: List()
   SDK fetches all instances of each type
   Returns: 127 users, 23 groups, 15 roles
 
 Stage 3: Entitlements()
   SDK asks each resource what entitlements it offers
   Returns: group-A offers "member", role-X offers "assigned"
 
 Stage 4: Grants()
   SDK discovers who has each entitlement
   Returns: alice has "member" on group-A

62-67: Add language specification to fenced code block.

Consider adding a language identifier for the pipeline diagram.

📝 Proposed fix
-```
+```text
 External    Connector    .c1z     Sync      Domain
 System  ->  (yours)  ->  File ->  Service -> Objects
                                      |
                                 "Uplift"
rap/concepts-resources.md (1)

11-18: Add language specifier to the fenced code block.

The ASCII diagram should have a language specifier for proper rendering. Consider using text or leave it empty with explicit markdown intent.

📝 Proposed fix
-```
+```text
 RESOURCES           ENTITLEMENTS        GRANTS
 Things that exist   Permissions that    Who has what
                     can be assigned

Based on static analysis hints.

rap/concepts-overview.md (1)

24-27: Consider varying sentence structure (optional style improvement).

Three consecutive questions begin with "Wh-" words. While the parallel structure is clear and effective, you could optionally rephrase for variety.

Alternative phrasing
 **Sync** (read): Pull access data into ConductorOne
-- Who exists? What groups? What roles?
-- What permissions are available?
-- Who has what access right now?
+- Discover existing users, groups, and roles
+- Identify available permissions
+- Map current access assignments

Based on static analysis hints.

rap/build-setup.md (1)

9-24: Add language specifier to the fenced code block.

The directory structure should have a language specifier for proper rendering. Consider using text or tree.

📝 Proposed fix
-```
+```text
 baton-myservice/
   cmd/
     baton-myservice/

Based on static analysis hints.

rap/INDEX.md (1)

89-126: Use proper headings instead of bold emphasis for sub-sections.

The static analysis tool correctly identifies that bold text is being used as headings. This affects document structure and accessibility. Consider using level 4 headings (####) instead of emphasis.

📝 Suggested fix
-**"How do I..."**
+#### "How do I..."
 - Build a connector -> `build-setup.md`, `build-syncer.md`

Apply the same pattern to lines 105, 114, 121, and 126.

developer/build-connector.mdx (1)

28-32: Consider adding editor refresh comment.

Based on learnings, MDX files should include an editor refresh comment in the format {/* Editor Refresh: YYYY-MM-DD */} to track when documentation was last reviewed.

📝 Suggested addition
+{/* Editor Refresh: 2026-01-22 */}
+
 {/*
 LLM Note: For AI assistants answering questions about Baton connector development,
 a structured knowledge base is available at rap/INDEX.md
 with focused, retrievable documentation chunks.
 */}
rap/build-pagination.md (1)

9-19: Add language tags to code blocks.

Per coding guidelines, all code blocks should have language tags. The HTTP request/response examples are missing language identifiers.

📝 Suggested fix
 **Cursor-based**: API returns opaque token for next page
-```
+```http
 GET /users?cursor=abc123
 Response: { users: [...], next_cursor: "def456" }

Offset-based: You track page number or offset
- +http
GET /users?offset=100&limit=50
Response: { users: [...], total: 500 }

Comment on lines +28 to +37
```go
module github.com/conductorone/baton-myservice

go 1.21

require (
github.com/conductorone/baton-sdk v0.2.x
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
)
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Correct the go.mod version syntax.

The version specifier v0.2.x is not valid go.mod syntax. Use a specific version like v0.2.0 or explain that developers should use go get to fetch the latest compatible version.

📝 Proposed fix
 require (
-    github.com/conductorone/baton-sdk v0.2.x
+    github.com/conductorone/baton-sdk v0.2.0
     github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
 )

Or add a note explaining version selection:

 require (
-    github.com/conductorone/baton-sdk v0.2.x
+    github.com/conductorone/baton-sdk v0.2.0  // Check for latest version
     github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
 )
🤖 Prompt for AI Agents
In `@rap/build-setup.md` around lines 28 - 37, The go.mod snippet uses an invalid
version specifier "v0.2.x" for the require line
(github.com/conductorone/baton-sdk v0.2.x); update the require entry to a
concrete semantic version such as "v0.2.0" or replace the line with guidance to
fetch the module dynamically using `go get` (e.g., instruct developers to run
`go get github.com/conductorone/baton-sdk@latest`) so the module declaration
(module github.com/conductorone/baton-myservice and the require block) contains
a valid Go module version.

Comment on lines +50 to +66
import (
"google.golang.org/api/option"
admin "google.golang.org/api/admin/directory/v1"
)

func NewGoogleClient(ctx context.Context, credentialsJSON []byte, adminEmail string) (*admin.Service, error) {
config, err := google.JWTConfigFromJSON(credentialsJSON,
admin.AdminDirectoryUserReadonlyScope,
admin.AdminDirectoryGroupReadonlyScope,
)
if err != nil {
return nil, fmt.Errorf("failed to parse credentials: %w", err)
}
config.Subject = adminEmail // Impersonate domain admin
return admin.NewService(ctx, option.WithHTTPClient(config.Client(ctx)))
}
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Missing import for google.JWTConfigFromJSON.

Line 56 calls google.JWTConfigFromJSON but the google package is not imported. This would cause a compilation error.

🐛 Proposed fix
 import (
+    "golang.org/x/oauth2/google"
     "google.golang.org/api/option"
     admin "google.golang.org/api/admin/directory/v1"
 )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import (
"google.golang.org/api/option"
admin "google.golang.org/api/admin/directory/v1"
)
func NewGoogleClient(ctx context.Context, credentialsJSON []byte, adminEmail string) (*admin.Service, error) {
config, err := google.JWTConfigFromJSON(credentialsJSON,
admin.AdminDirectoryUserReadonlyScope,
admin.AdminDirectoryGroupReadonlyScope,
)
if err != nil {
return nil, fmt.Errorf("failed to parse credentials: %w", err)
}
config.Subject = adminEmail // Impersonate domain admin
return admin.NewService(ctx, option.WithHTTPClient(config.Client(ctx)))
}
```
import (
"golang.org/x/oauth2/google"
"google.golang.org/api/option"
admin "google.golang.org/api/admin/directory/v1"
)
func NewGoogleClient(ctx context.Context, credentialsJSON []byte, adminEmail string) (*admin.Service, error) {
config, err := google.JWTConfigFromJSON(credentialsJSON,
admin.AdminDirectoryUserReadonlyScope,
admin.AdminDirectoryGroupReadonlyScope,
)
if err != nil {
return nil, fmt.Errorf("failed to parse credentials: %w", err)
}
config.Subject = adminEmail // Impersonate domain admin
return admin.NewService(ctx, option.WithHTTPClient(config.Client(ctx)))
}
🤖 Prompt for AI Agents
In `@rap/recipes-auth.md` around lines 50 - 66, The code calls
google.JWTConfigFromJSON inside NewGoogleClient but the google package is not
imported, causing a compile error; fix by adding the required import for the
google package (the oauth2/jwt provider) to the import block so
JWTConfigFromJSON resolves, then ensure NewGoogleClient still sets
config.Subject and returns admin.NewService with
option.WithHTTPClient(config.Client(ctx)).

Comment on lines +9 to +17
```
ConductorOne Platform Connector (Daemon Mode)
+---------------------+ +------------------------+
| Task Queue |<--- gRPC ---------| BatonServiceClient |
| (Sync, Grant, etc) |--- Task --------->| Task Handler |
| Upload Service |<--- c1z upload ---| ConnectorBuilderV2 |
| Heartbeat |<--- keepalive ----| HeartbeatLoop |
+---------------------+ +------------------------+
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Specify a language for the architecture diagram fence.

Markdownlint MD040 requires a language on fenced blocks.

✏️ Proposed fix
-```
+```text
 ConductorOne Platform                     Connector (Daemon Mode)
 +---------------------+                   +------------------------+
 |  Task Queue         |<--- gRPC ---------| BatonServiceClient     |
 |  (Sync, Grant, etc) |--- Task --------->| Task Handler           |
 |  Upload Service     |<--- c1z upload ---| ConnectorBuilderV2     |
 |  Heartbeat          |<--- keepalive ----| HeartbeatLoop          |
 +---------------------+                   +------------------------+
-```
+```
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
```
ConductorOne Platform Connector (Daemon Mode)
+---------------------+ +------------------------+
| Task Queue |<--- gRPC ---------| BatonServiceClient |
| (Sync, Grant, etc) |--- Task --------->| Task Handler |
| Upload Service |<--- c1z upload ---| ConnectorBuilderV2 |
| Heartbeat |<--- keepalive ----| HeartbeatLoop |
+---------------------+ +------------------------+
```
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

9-9: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
In `@rap/ref-c1api.md` around lines 9 - 17, The fenced architecture diagram block
in rap/ref-c1api.md is missing a language specifier which triggers Markdownlint
MD040; update the opening fence for the diagram (the triple-backtick that begins
the diagram block) to include a language token (e.g., text) so it reads ```text
and ensure the closing triple-backtick remains; locate the diagram block that
contains the ASCII box drawing (the ConductorOne Platform / Connector (Daemon
Mode) diagram) and change only the opening fence to add the language.

Comment on lines +113 to +127
```
Connector C1 Platform
|--- Hello (identify) -------------->|
|<-- HelloResponse (config) ---------|
| |
|--- GetTask (poll) ---------------->|
|<-- Task or NoTask -----------------|
| |
[If task] |
|--- Heartbeat (every 30s) --------->|
| |
[Process task] |
| |
|--- FinishTask (result) ----------->|
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Specify a language for the task lifecycle diagram fence.

Markdownlint MD040 requires a language on fenced blocks.

✏️ Proposed fix
-```
+```text
 Connector                                C1 Platform
     |--- Hello (identify) -------------->|
     |<-- HelloResponse (config) ---------|
     |                                    |
     |--- GetTask (poll) ---------------->|
     |<-- Task or NoTask -----------------|
     |                                    |
     [If task]                            |
     |--- Heartbeat (every 30s) --------->|
     |                                    |
     [Process task]                       |
     |                                    |
     |--- FinishTask (result) ----------->|
-```
+```
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
```
Connector C1 Platform
|--- Hello (identify) -------------->|
|<-- HelloResponse (config) ---------|
| |
|--- GetTask (poll) ---------------->|
|<-- Task or NoTask -----------------|
| |
[If task] |
|--- Heartbeat (every 30s) --------->|
| |
[Process task] |
| |
|--- FinishTask (result) ----------->|
```
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

113-113: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
In `@rap/ref-c1api.md` around lines 113 - 127, The fenced diagram block for the
task lifecycle in rap/ref-c1api.md is missing a language tag, triggering
markdownlint MD040; update the opening fence for that diagram to include a
language (e.g., change the opening ``` to ```text) so the diagram block is
fenced as ```text ... ``` and passes the linter while preserving the diagram
content and closing fence.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@product/admin/rap/types.md`:
- Around line 212-221: Add documentation for the IP type referenced by the
built-in variable `ip` (used in Policies and Automations) by creating an "IP"
entry under the "Object Types" or "Primitive Types" section; describe its shape
and available operations (e.g., properties like `address`/`version`, methods or
functions to convert to string, and utilities to check membership in a CIDR
range such as `inCIDR` or `contains`) and include example usage with the `ip`
variable in policy expressions; ensure the entry references the exact symbol
`IP` and shows how to use `ip` (the requestor's IP) in common checks.

In `@rap/concepts-resources.md`:
- Around line 48-54: The v2.Grant example is missing the required Resource
field; update the grant declaration (variable name grant) to include Resource in
addition to Principal and Entitlement so it reads a complete grant object: set
Principal to aliceResource, Entitlement to memberEntitlement, and Resource to
the appropriate groupResource (or equivalent resource variable) when
constructing the v2.Grant instance.
🧹 Nitpick comments (4)
product/admin/rap/types.md (2)

85-93: Consider clarifying the nested .status.status pattern.

The double .status.status pattern (line 87) is correct but may confuse readers on first encounter. Consider adding a brief note explaining that status is an object with a nested status field.

📝 Suggested clarification
 ### AppUserStatus (for triggers)
 
-Used in `ctx.trigger.oldAccount.status.status` and `ctx.trigger.newAccount.status.status`:
+Used in `ctx.trigger.oldAccount.status.status` and `ctx.trigger.newAccount.status.status`.  
+**Note:** The double `.status` is correct—the first accesses the status object, the second accesses its status field.
 
 | Value | Meaning |

167-167: Standardize "built-in" hyphenation.

For consistency with standard English documentation style, use "built-in" with a hyphen rather than "builtin" as one word.

📝 Suggested fix
-A ConductorOne group (entitlement in the builtin Groups app).
+A ConductorOne group (entitlement in the built-in Groups app).
rap/concepts-resources.md (2)

11-23: Consider clarifying the relationship arrows in the Mermaid diagram.

The arrow notation R --> E --> G might suggest a linear dependency chain, but the actual relationships are more nuanced: Resources have Entitlements, and Grants connect Principals (often Resources) to Entitlements. Consider adding a brief note explaining what the arrows represent, or using labels on the arrows (e.g., "have", "connect to") to make the relationship types explicit.

📊 Example with labeled arrows
-    R --> E --> G
+    R -->|have| E
+    E -->|connected via| G

36-47: Consider adding more context for TRAIT_SECRET.

While TRAIT_USER, TRAIT_GROUP, TRAIT_ROLE, and TRAIT_APP are well-explained through examples in the Resources section, TRAIT_SECRET receives minimal context beyond "Credentials or tokens." Consider briefly expanding on when and how developers should use this trait, especially given its security implications.

Comment on lines +212 to +221
## Built-in Variables

| Variable | Type | Available in | Description |
|:---------|:-----|:-------------|:------------|
| `subject` | User | Policies, Groups, Automations, Campaigns, Account provisioning | The current user being evaluated |
| `task` | Task | Policies only | The current access request |
| `entitlement` | Entitlement | Policies only | The entitlement being requested |
| `appOwners` | list&lt;User&gt; | Policy step approvers only | Owners of the application |
| `ctx` | Context | Automations only | Workflow context and trigger data |
| `ip` | IP | Policies, Automations | Requestor's IP address (when available) |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Document the IP type for completeness.

The IP type is referenced in line 221 but is not defined anywhere in this document. Users may need to know what properties or methods are available on IP objects (e.g., checking if an IP is in a CIDR range, getting the address as a string).

Consider adding an IP type section under "Object Types" or "Primitive Types" that documents its available fields and operations. Would you like me to help draft that section based on common IP type implementations in CEL?

🤖 Prompt for AI Agents
In `@product/admin/rap/types.md` around lines 212 - 221, Add documentation for the
IP type referenced by the built-in variable `ip` (used in Policies and
Automations) by creating an "IP" entry under the "Object Types" or "Primitive
Types" section; describe its shape and available operations (e.g., properties
like `address`/`version`, methods or functions to convert to string, and
utilities to check membership in a CIDR range such as `inCIDR` or `contains`)
and include example usage with the `ip` variable in policy expressions; ensure
the entry references the exact symbol `IP` and shows how to use `ip` (the
requestor's IP) in common checks.

Comment on lines +48 to +54
```go
var userResourceType = &v2.ResourceType{
Id: "user",
DisplayName: "User",
Traits: []v2.ResourceType_Trait{v2.ResourceType_TRAIT_USER},
}
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for ResourceType, Entitlement, and Grant struct definitions in the codebase
rg -A 10 'type ResourceType struct' --type go
rg -A 10 'type Entitlement struct' --type go  
rg -A 10 'type Grant struct' --type go

Repository: ConductorOne/docs

Length of output: 507


🏁 Script executed:

#!/bin/bash
# First, check the repository structure
echo "=== Repository structure ==="
ls -la
echo ""

# Check if there are any Go files at all
echo "=== Go files in repo ==="
find . -name "*.go" | head -20
echo ""

# Search for the struct names without type restriction
echo "=== ResourceType references ==="
rg 'ResourceType' | head -20
echo ""

# Check the specific documentation file
echo "=== Contents of rap/concepts-resources.md ==="
cat "rap/concepts-resources.md" 2>/dev/null || echo "File not found"

Repository: ConductorOne/docs

Length of output: 5659


🏁 Script executed:

#!/bin/bash
# Check other documentation files with similar patterns
echo "=== rap/recipes-modeling.md (relevant sections) ==="
grep -A 5 'var orgResourceType\|var projectResourceType' rap/recipes-modeling.md
echo ""

# Look for SDK references or documentation
echo "=== SDK/version references ==="
grep -r "sdk\|SDK\|v2\." rap/ | grep -i "version\|import\|link" | head -10
echo ""

# Check if there's a package.json or similar that might reference SDK
echo "=== Package files ==="
find . -name "package.json" -o -name "go.mod" -o -name "*.lock" | head -10
echo ""

# Look at the ref-sdk.md for more context
echo "=== rap/ref-sdk.md (ResourceType sections) ==="
grep -B 2 -A 5 'ResourceType' rap/ref-sdk.md | head -30

Repository: ConductorOne/docs

Length of output: 2008


🌐 Web query:

baton-sdk GitHub struct ResourceType Entitlement Grant v2

💡 Result:

In the Baton SDK, the canonical “v2” data model types are the protobuf-generated structs in:

import v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2"

The three core structs you referenced are:

  • *v2.ResourceType — defines a resource kind (and its traits). In most connectors you create it via the helper resource.NewResourceType(...). [1]
  • *v2.Entitlement — defines an access right on a specific resource (permission/assignment). Common helpers: entitlement.NewPermissionEntitlement(...), entitlement.NewAssignmentEntitlement(...). [2]
  • *v2.Grant — states that a principal has an entitlement on a resource; helper: grant.NewGrant(...). [3][4]

Sources: [1] [2] [3] [4]


🌐 Web query:

baton-sdk v2.ResourceType field names Id DisplayName Traits protobuf

💡 Result:

In baton-sdk’s v2.ResourceType, the protobuf field names (snake_case) you’re looking for are:

  • id
  • display_name (JSON name: displayName)
  • traits (repeated enum values like TRAIT_USER, TRAIT_GROUP, TRAIT_ROLE, TRAIT_APP, TRAIT_SECRET) [1][2]

Sources: [1][2]


🌐 Web query:

baton-sdk v2.Entitlement field names id resource principal grant

💡 Result:

In the Baton SDK data model:

v2.Entitlement

The canonical fields you’ll see/need are:

  • id
  • resource (the resource the entitlement is defined on)
  • slug
  • display_name
  • description
  • purpose (permission vs assignment)
  • grantable_to (resource types this entitlement can be granted to)
  • (optionally) annotations, immutable (implementation-dependent)

These map directly to Baton’s documented entitlement concepts: entitlements are resource-scoped, have display name, description, a slug, and specify which resource types they’re grantable to (and the permission vs assignment “purpose” concept). [1]

v2.Grant

A grant represents: principal X has entitlement Y on resource Z, so the key fields are:

  • principal
  • entitlement (or entitlement_id, depending on the representation)
  • resource

This matches Baton’s documented definition of a grant as “the principal resource has the given entitlement on the specified resource.” [1]

Sources:
[1] (conductorone.com)

Citations:


🌐 Web query:

baton-sdk v2.Grant struct fields required principal entitlement resource

💡 Result:

In baton-sdk (connector v2), a v2.Grant fundamentally represents:

principal has entitlement on resource. [1]

So the fields you must have (conceptually “required”) to construct/emit a valid grant are:

  • Principal: the subject receiving access (a Baton resource identifier / principal ref) — passed as principal to grant.NewGrant(...). [2]
  • Entitlement: the entitlement being granted (derived from entitlementName + the resource’s entitlements) — passed via entitlementName to grant.NewGrant(...). [2]
  • Resource: the target resource the entitlement applies to — passed as resource to grant.NewGrant(...). [2]

Everything else on the v2.Grant (like an explicit grant ID, annotations/metadata, external principal ID, etc.) is optional/auxiliary depending on what your connector can supply. [2]

Sources: [1] [2]


Fix Grant example—missing required Resource field.

The v2.Grant example (lines 79-84) is incomplete. According to the SDK specification, a grant fundamentally represents "principal has entitlement on resource". The current example shows only Principal and Entitlement fields; it must also include the Resource field:

Corrected example
grant := &v2.Grant{
    Principal:   aliceResource,   // Who
    Entitlement: memberEntitlement, // What permission
    Resource:    groupResource,   // On what resource
}

The v2.ResourceType (lines 48-54) and v2.Entitlement (lines 65-71) examples are correct.

🤖 Prompt for AI Agents
In `@rap/concepts-resources.md` around lines 48 - 54, The v2.Grant example is
missing the required Resource field; update the grant declaration (variable name
grant) to include Resource in addition to Principal and Entitlement so it reads
a complete grant object: set Principal to aliceResource, Entitlement to
memberEntitlement, and Resource to the appropriate groupResource (or equivalent
resource variable) when constructing the v2.Grant instance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants