Permissions

There is one permission system, and everything outside the app uses it: the REST API, the MCP server an assistant speaks, and the calendar link. A token holds scopes; every endpoint and every tool names the one it needs; the two are compared on every call. There is no second model to keep in step and no grant that means different things at different doors.

Three habits shape the list. Reading and writing are separate grants — a token that reports your day cannot rewrite it. Deleting is separate again: the tools that remove a row for good need the destructive grant on top of the room's own write scope, because a wrong write is data that is wrong and a wrong delete is data that is gone. And each sentence is what the person consents to: the key is for developers, the sentence is for whoever owns the data, and the picker shows the sentence.

Grant the narrowest set that works. A token lives on a phone, in a config file, in somebody else's service — what it cannot read cannot leak.

Pictures and recordings come with what refers to them

A file has no permission of its own. It answers to whatever it is used in: a picture pasted into a note is reachable by a key with notes:read, a screenshot on a task by tasks:read, somebody's face by people:read, a recipe's photograph by kitchen:read, and a recording by whichever of those holds it. A file nothing refers to is reachable by nobody.

There is no media:read, deliberately. Granting "you may read my notebooks" and then asking a second question about the pictures inside them is the same question twice, and two answers that can disagree — a note readable but its photographs not, for no reason anybody chose. The grant a file needs is the grant its referrer needs.

An assistant speaking MCP asks for one with the media tool, handing it the link the writing already gave it:

{ "name": "media", "arguments": { "path": "/media/31" } }

A script holding the key itself fetches the same file the way a browser does:

curl -H "Authorization: Bearer $ONTOPLANO_KEY" \
  https://your-instance/media/31 --output picture.png

curl -H "Authorization: Bearer $ONTOPLANO_KEY" \
  https://your-instance/media/audio/44 --output recording.webm

Either way the link is the one written into the markdown — ![a photo](/media/31) and [said](/media/audio/44) — so a tool that reads a note hands over everything needed to reach what is in it.

A file the key may not reach answers 404, the same as one that does not exist. That is on purpose: a different answer for "exists but not yours" is a way to count somebody else's pictures one id at a time.

One gap worth knowing: a picture that lives only in a gallery album is reachable by nobody. The gallery has never had a scope of its own, and this is not the change that invents one.

Tying a key to one thing

A scope is about the account: tasks:write is every to-do there is. The thing people usually want to hand an assistant is narrower than that — work on this project with me — so a key can also be tied to a single notebook. Such a key sees that notebook and everything filed under it: the notes written in it and the pictures and recordings inside those, its tasks and goals, and whatever else it has been switched on to hold — its shopping, its bills, the account they are paid from. Everything else in the account is not refused to it; it is not there.

The narrowing is not a filter the tools apply. Each tool declares which of its arguments name a thing and what kind, and the id is resolved against the rows that key can list — which for a tied key is the contents of its one notebook. So a tool that would be about the account rather than a thing, diary or goals, is not offered to it at all, and the permissions it can still be granted are only the rooms its notebook reaches. Asking it about a different notebook is answered about its own: a refusal that depended on the other notebook existing would be a way to ask what the account has, one number at a time.

Choose it where the key is made, above the permissions: What it may work on.

One thing to know before granting a :write on its own: writing does not imply reading, and most changes name the thing they change by the id the matching read handed out. tasks:write alone can add a todo and cannot find the todo you asked it to finish. Where naming a thing is unambiguous the write tool takes a name instead — tick_habit accepts "stretching" — so habits:write on its own is a usable grant. Everywhere else, pair the two. The token form says so under the tick rather than leaving you to find out from an assistant that cannot do what you asked.

Scope What granting it allows MCP tools behind it
streams:write Send readings into your data streams, and create new streams log_data_point
streams:read Read everything your data streams have ever recorded data_streams
schedule:read Read everything on your calendar for the days ahead, today included upcoming, past, reminders, repeating_week, categories, activities
schedule:write Put blocks on your week — one-off and repeating — move and rename them, take them off a day, set reminders on them, and mark them done or skipped finish_block, add_block, change_block, cancel_block, set_alarm, change_reminder, cancel_alarm, remind_before_block, dismiss_reminder, add_repeating_block, change_repeating_block, remove_repeating_block, add_activity, change_activity, remove_activity
today:read See today's plan — the blocks and the tasks on it today
reminders:read See the reminders you have coming, so this device can ring for them —
habits:read See your habits, which are due today, and whether you kept them habits, all_habits
habits:write Mark a habit kept, or unmark one tick_habit, set_habit_count, add_habit, change_habit, archive_habit, unarchive_habit
plugin:declare Name and describe itself on your integrations page —
webhooks:manage Send itself a message when something changes here — a task finished, a block done — to an address it chooses —
audio:read Read your recordings and their notes recordings
audio:write Rename your recordings and write their notes change_recording
inventory:read See everything you keep and everything on your shopping list shopping_list, inventory_categories, inventory_attributes
inventory:write Add things, tick them bought, change how many you keep, and take things off add_inventory_item, tick_bought, untick_bought, archive_item, unarchive_item, remove_inventory_item, file_inventory_item, change_inventory_item, add_inventory_category, change_inventory_category, move_inventory_category, remove_inventory_category, record_price, set_item_attributes, change_inventory_attribute, remove_inventory_attribute
locations:read See where your things live, and what is in each room and drawer where_is, locations
locations:write Add and change rooms and drawers, and say where a thing lives add_location, change_location, remove_location, put_item
calendar:read Show your plan in a calendar app. It can see the plan and change nothing —
notes:read Read your diary and your notebooks, and the pictures and recordings in them media, diary, notebook_notes, notebooks, daily_wins
notes:write Write in your diary and your notebooks write_entry, pin_note, unpin_note, edit_entry, archive_note, unarchive_note, move_notes, add_notebook, change_notebook, rename_notebook_folder, remove_notebook, favourite_notebook, share_notebook, record_win
ideas:read See your ideas, and the pictures and recordings in them ideas
ideas:write Add ideas, change them, and remove them add_idea, remove_idea, change_idea, apply_idea, favorite_idea
tasks:read Read your todo list and your goals, and the pictures and recordings on them tasks, up_next, goals, goal_areas, weekly_review
tasks:write Add, finish and delete todos, move them on and off a day, and close a goal add_task, finish_task, drop_task, reopen_task, archive_task, unarchive_task, tag_task, change_task, reorder_tasks, schedule_task, unschedule_task, close_goal, link_to_goal, unlink_from_goal, reopen_goal, change_goal, note_to_tasks, add_goal, log_goal_progress, add_goal_target, remove_goal_target, add_goal_area, change_goal_area, move_goal_area, remind_task, write_review_note
kitchen:read Read your recipes, and their photographs recipes
kitchen:write Add and change recipes add_recipe, change_recipe, cooked_recipe, archive_recipe
workouts:read See your workouts workouts, workout_sessions, workout_history, workout_activities, workout_categories
workouts:write Add and change workouts and their categories, put them away, and mark one done set_workout_measures, log_workout, change_workout_session, remove_workout_session, add_workout_category, change_workout_category, remove_workout_category, add_workout, change_workout, archive_workout, workout_done
bills:read See your bills, your recorded income, and what you have actually paid or received bills, bill_payments, bill_history, month_bills, bills_due
statements:read Read your imported bank-statement lines, their categories and tags, and the monthly in/out figures budgets, personal_spending, summary, commitments, commitment_entries, ledgers, balance_checks, statement_months, spending_by_category, movements, sort_rules
statements:write Add and remove the rules that sort your statement lines add_budget, change_budget, delete_budget, copy_budgets, add_commitment, change_commitment, archive_commitment, close_commitment, record_commitment_entry, delete_commitment_entry, settle_commitment, consume_reserve, split_movement, unsplit_movement, add_ledger, change_ledger, record_balance_check, delete_balance_check, record_movement, change_movement, classify_movements, link_transfer, unlink_transfer, link_movement, remove_movement, change_sort_rule, add_sort_rule, delete_sort_rule
bills:write Add and change bills, and mark them paid add_bill, change_bill, archive_bill, pay_bill, change_bill_payment, unpay_bill, skip_bill, unskip_bill
people:read See the people in your life, whose birthday is coming, and their photographs people, upcoming_birthdays
people:write Add people, and change what is recorded about them add_person, change_person
search:read Search everything you have written, in one go.
Careful: One grant that reads across everything — diary, notebooks, ideas, goals, people, recipes and todos. Only for something you would show all of that.
search
tags:read See the labels you use, and the colours you gave them tags, notebook_tags
tags:write Rename your labels, colour them, and merge two into one describe_tag, rename_tag, recolor_tag, remove_tag, untag_notebook
destructive Delete things outright — with only the write grants, it can add and change but never remove.
Careful: What this deletes is gone. Leave it off unless you want the token removing things, not just adding and changing them.
cancel_block, drop_task, remove_notebook, remove_idea, remove_tag, remove_inventory_item, remove_inventory_category, remove_goal_target, cancel_alarm, remove_repeating_block, remove_activity, remove_location, remove_inventory_attribute, remove_workout_session, remove_workout_category, delete_budget, delete_commitment_entry, delete_balance_check, remove_movement, delete_sort_rule
notebooks:deliver File things into your other notebooks, and move this notebook’s things there — seeing only their names, never what is in them —

The REST side of the same table — which endpoint asks for which scope — is generated into the API page.