Ownership
Manage query ownership and transfer queries between users and teams.
Query Ownership Overview
Every query has an ownerId that determines:
- Default Permissions - Owner has full access
- Team Access - Team members inherit access via roles
- Sharing Base - Who can grant additional shares
- Natural ID - Slug-based ID includes owner
Ownership can be:
- User - Individual user account (
john.doe) - Team - Team identifier (
team:analytics)
GET /api/queries/{id}/owner
Get the owner (user or team) of a query.
Authentication: Required
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | Query ID (UUID) or natural ID |
Response (User Owner):
{
"id": "john.doe",
"username": "john.doe",
"displayName": "John Doe",
"email": "john.doe@company.com",
"avatar": "/api/users/john.doe/avatar",
"_links": {
"self": { "href": "/api/users/john.doe" }
}
}
Response (Team Owner):
{
"id": "team:analytics",
"name": "Analytics Team",
"slug": "analytics",
"description": "Data analytics and reporting team",
"memberCount": 12,
"_links": {
"self": { "href": "/api/teams/team:analytics" }
}
}
PUT /api/queries/{id}/owner
Transfer ownership of a query to a different user or team.
Authentication: Required
Permission: query:write
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | Query ID (UUID) or natural ID |
Request Body:
{
"id": "team:analytics"
}
Or:
{
"username": "jane.smith"
}
Validation:
Provide either:
id- Principal ID (user or team)username- User username
Response:
Returns the updated query with new owner.
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"naturalId": "team:analytics:sales-query",
"name": "Sales Analysis Query",
"ownerId": "team:analytics",
"updatedAt": "2024-02-09T12:00:00Z",
"_links": {
"self": { "href": "/api/queries/team:analytics:sales-query" }
}
}
Activity Tracking:
Transferring ownership creates a queryAssigned activity entry.
Transferring ownership changes the query's natural ID from oldOwner:slug to newOwner:slug. Update any references or bookmarks.
Ownership Best Practices
When to Use Team Ownership
| Scenario | Ownership Type |
|---|---|
| Departmental queries | Team |
| Personal/experimental queries | User |
| Shared reporting queries | Team |
| Production queries | Team |
| Draft/development queries | User |
| Administrative queries | Team (admin team) |
Transfer Workflow
- Verify Permissions - Ensure you have write access to the query
- Notify Stakeholders - Inform users of ownership change
- Transfer Ownership - Use
PUT /api/queries/{id}/owner - Update Documentation - Update any references to old natural ID
- Verify Access - Ensure new owner has necessary datasource access
Team Ownership Advantages
- Continuity - Queries persist when users leave
- Shared Responsibility - Team members can maintain queries
- Access Management - Automatic role-based permissions
- Organization - Queries grouped by team/department
- Discoverability - Easy to find team-related queries
Ownership Scenarios
Transfer User Query to Team
# User creates a query
POST /api/queries
{
"name": "Sales Analysis",
"language": "sql",
"datasourceId": "mysql-prod",
"payload": { "sql": "SELECT * FROM sales" }
}
# Query is owned by current user
# naturalId: john.doe:sales-analysis
# Transfer to team when promoting to production
PUT /api/queries/john.doe:sales-analysis/owner
{
"id": "team:analytics"
}
# Query now team-owned
# naturalId: team:analytics:sales-analysis
Transfer Between Teams
# Query currently owned by Analytics team
GET /api/queries/team:analytics:revenue-query
# Transfer to Finance team
PUT /api/queries/team:analytics:revenue-query/owner
{
"id": "team:finance"
}
# Query now owned by Finance
# naturalId: team:finance:revenue-query
Assign to Specific User
# Make a specific user responsible for maintenance
PUT /api/queries/team:analytics:sales-query/owner
{
"username": "jane.smith"
}
# Query now owned by Jane
# naturalId: jane.smith:sales-query
Ownership and Permissions
Permission Inheritance
Ownership affects permissions:
| Owner Type | Permission Model |
|---|---|
| User | Owner has all permissions; others need explicit shares |
| Team | Team members get role-based permissions; non-members need shares |
Team Role Permissions
For team-owned queries:
| Role | Permissions |
|---|---|
| Admin | All permissions |
| Publisher | Run, edit, share |
| Data Wizard | Run, edit (if embedded) |
| Designer | Run, edit (if ad-hoc) |
| Member | Run only |
Ownership Transfer Permissions
To transfer ownership, you must:
- Have
query:writepermission on the query - Verify the target principal exists
- Be the current owner OR team admin
Having write permission doesn't automatically grant ownership transfer rights. Ownership transfer is a privileged operation typically reserved for owners and team admins.
Natural ID Management
Natural ID Structure
- User-owned:
username:slug(e.g.,john.doe:sales-query) - Team-owned:
team:teamSlug:slug(e.g.,team:analytics:sales-query) - UUID fallback: If no slug, uses UUID
Handling Natural ID Changes
When ownership changes, the natural ID changes. To maintain references:
// Before transfer - store UUID
const query = await GET('/api/queries/john.doe:sales-query');
const queryUuid = query.id;
// Transfer ownership
await PUT(`/api/queries/${queryUuid}/owner`, {
id: 'team:analytics'
});
// After transfer - use UUID or new natural ID
const updated = await GET(`/api/queries/${queryUuid}`);
console.log(updated.naturalId); // team:analytics:sales-query
Slug Conflicts
If the target owner already has a query with the same slug:
- Informer may auto-append a number:
sales-query-2 - Or return a conflict error
- Consider renaming before transfer to avoid conflicts
Bulk Ownership Transfer
Transfer multiple queries at once:
// Get all user's queries
const queries = await GET('/api/queries?owner=john.doe');
// Transfer to team
for (const query of queries.items) {
await PUT(`/api/queries/${query.id}/owner`, {
id: 'team:analytics'
});
}
Ownership Audit
List Queries by Owner
# Get all queries owned by user
GET /api/queries?owner=john.doe
# Get all queries owned by team
GET /api/queries?owner=team:analytics
# Get all queries (admins only)
GET /api/queries
Find Orphaned Queries
Queries owned by deleted users/teams may need reassignment:
// Check owner validity
const query = await GET('/api/queries/unknown-user:old-query');
if (query.ownerId && !query.owner) {
// Owner doesn't exist - reassign
await PUT(`/api/queries/${query.id}/owner`, {
id: 'team:admin'
});
}
Security Considerations
- Verify Access - Ensure new owner has datasource access
- Audit Transfers - Review ownership changes via activity log
- Limit Transfer Permission - Restrict who can transfer ownership
- Team Ownership - Prefer team ownership for shared resources
- Document Ownership - Maintain documentation of query ownership policies