Initial QSfera import
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
---
|
||||
title: "1. Simple Multi-Tenancy using a single КуСфера Instance"
|
||||
---
|
||||
|
||||
* Status: proposed
|
||||
* Deciders: [@micbar @butonic @dragotin @rhafer]
|
||||
* Date: 2025-05-20
|
||||
|
||||
Technical Story: https://github.com/qsfera/server/issues/877
|
||||
|
||||
## Context and Problem Statement
|
||||
|
||||
To reduce resource usage and cost service providers want a single КуСфера
|
||||
instance to host multiple tenants. Members of the same tenant should be able to
|
||||
only see each other when trying to share resources. A user can only be a member
|
||||
of a single tenant. Moving a user from one tenant to another is not supported.
|
||||
|
||||
КуСфера does currently not have any concept of multi-tenancy. All users able to
|
||||
login to an КуСфера instance are able to see each other and share resources with
|
||||
everybody. This ADR is supposed to layout a concept for a minimal multi-tenancy
|
||||
solution that implements the characteristics mentioned above.
|
||||
|
||||
To further limit the scope there are a couple of constraints:
|
||||
|
||||
- Tenants are rather small (sometimes just a single user, often less than 10)
|
||||
- There is just a single IDP with a single "realm".
|
||||
- The user-management is external to КуСфера
|
||||
- The membership of a user to a tenant is represented by a tenant id
|
||||
that is provided via a claim in the users' Access Token/UserInfo or by a per User
|
||||
Attribute in the LDAP directory.
|
||||
- There is no need to support per tenant groups
|
||||
- There is no need to isolate the storage of the tenants from each other
|
||||
- Role Assignment happens at first login via OIDC claims
|
||||
|
||||
## Decision Drivers
|
||||
|
||||
* Low Resource Overhead: The solution should not require much additional
|
||||
resources (CPU, Memory, Storage) per tenant on the КуСфера instance.
|
||||
* Implementation effort: The solution should be easy to implement and maintain.
|
||||
* Security: The solution should prevent users from seeing or accessing anything
|
||||
from other tenants.
|
||||
|
||||
## Considered Options
|
||||
|
||||
### Option 1: Tenant ID as a new property of the CS3 UserId
|
||||
|
||||
The CS3 UserId (https://buf.build/cs3org-buf/cs3apis/docs/main:cs3.identity.user.v1beta1#cs3.identity.user.v1beta1.UserId)
|
||||
is extended by a new property "tenantId".
|
||||
|
||||
#### Pros:
|
||||
|
||||
* Everywhere the UserID is used the tenant id is also available.
|
||||
* This might allow implementing more sophisticated checks e.g. on permission
|
||||
grants and to a certain extend during share creation.
|
||||
* the tenant id is immediately available e.g. in Events/Auditlog without an additional
|
||||
user lookup
|
||||
|
||||
#### Cons:
|
||||
|
||||
* Requires changes to the CS3 API
|
||||
* Adds even more semantics to the UserId. Ideally the UserID would just be an
|
||||
opaque identifier without carrying and specific semantics other than being
|
||||
globally unique.
|
||||
* on the GraphAPI the ID of a User is just a opaque string without any additional
|
||||
meaning. (Currently it is just using the `OpaqueId` property of the CS3 UserId,
|
||||
without considering the `idp` property.)
|
||||
|
||||
### Option 2: Tenant ID is stored as the `idp` value of the CS3 UserId
|
||||
|
||||
Instead of introducing a new property the on the CS3 UserId we'll just override
|
||||
the `idp` value with the tenant id.
|
||||
|
||||
#### Pros
|
||||
|
||||
* No changes to the CS3 API required
|
||||
* The pros of Option 1 apply here as well
|
||||
|
||||
#### Cons:
|
||||
|
||||
* It's a crutch, we're already "abusing" the `idp` property of the CS3 UserId
|
||||
to have a different meaning in the context of federated sharing. Adding an
|
||||
additiona meaning could make the code even more complicated.
|
||||
* Apart from the API change the Cons of Option 1 apply here as well.
|
||||
|
||||
### Option 3: Tenant ID is a property of the CS3 User Object
|
||||
|
||||
A new (optional) property "tenantId" is added to the CS3 User Object.
|
||||
|
||||
#### Pros:
|
||||
|
||||
* Avoid overloading CS3 UserId with additional semantics.
|
||||
* The tenant id is available everywhere the User Object is used.
|
||||
|
||||
#### Cons:
|
||||
|
||||
* Requires changes to the CS3 API
|
||||
* Might require more user lookups in places where we need to find out the
|
||||
tenant id of a specific user
|
||||
|
||||
### Option 4: Tenant ID is invisible to the CS3 API
|
||||
|
||||
Reva Tokens would get a new property `tenantId`. To have the tenant id available
|
||||
of the signed in user available with every request.
|
||||
While not being part of the CS3 API objects the `users` service will be made "tenant aware"
|
||||
so that is only returns users of the same tenant as the requesting user e.g. by using
|
||||
proper LDAP filters or subtree searches.
|
||||
|
||||
#### Pros:
|
||||
|
||||
* No changes to the CS3 API required
|
||||
* Code changes could be limited to the `users` and`share-provider` services and the reva token manager
|
||||
* The tenant id of the current user is available everywhere the reva token is used.
|
||||
|
||||
#### Cons:
|
||||
|
||||
* Can this work with the App Token feature if the Tenant Id is not part of the User Object in
|
||||
any way, how can the the token manager know with Id to add to the token?
|
||||
* What about places where the system user is doing stuff on behalf of a user
|
||||
|
||||
### Option 5: Tenant membership via LDAP group membership
|
||||
|
||||
All members of a tenant are assigned to the same group. The `users` service gets a config
|
||||
switch to only allow users to search for users that are part of the same group.
|
||||
|
||||
#### Pros:
|
||||
|
||||
* ?
|
||||
|
||||
#### Cons:
|
||||
|
||||
* The group needs to be hidden somehow from the `groups` service as this is not supposed to be a
|
||||
"sharing group".
|
||||
|
||||
## Decision Outcome
|
||||
|
||||
### Chosen option: Option 1 - Tenant ID as a new property of the CS3 UserId
|
||||
|
||||
As part of the OIDC Connect Authentication КуСфера will receive a tenant id via the
|
||||
Access Token or Userinfo endpoint. For the initial implementation it is assume that КуСфера
|
||||
has read access to a shared LDAP server, that contains all users of all tenants. Users in
|
||||
LDAP will have a the tenant id as an dedicated attribute.
|
||||
|
||||
### Implementation Steps
|
||||
|
||||
* Extend the CS3 UserId with a new property "tenantId"
|
||||
* Adapt the `users` service` to only return users that are part of the same tenant
|
||||
* To cleanup technical debt and reduce code duplication the `cs3` users backend in the
|
||||
graph service is being improved so that is can fully replace the `LDAP` users backend for
|
||||
read operations.
|
||||
* The reva `share-provider` service only allow shares between users of the same tenant
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
---
|
||||
title: "Use the graph education API for multi-tenant user provisioning"
|
||||
---
|
||||
|
||||
* Status: approved
|
||||
* Deciders: [@micbar, @butonic, @rhafer]
|
||||
* Date: 2025-09-23
|
||||
|
||||
Reference: https://github.com/qsfera/server/issues/877
|
||||
|
||||
## Context and Problem Statement
|
||||
|
||||
With the current multi-tenancy implementation, the user-management is mostly external
|
||||
to the КуСфера instance. Up to [now](../0001-simple-multi-tenancy-using-a-single-qsfera-instance.md)
|
||||
we relied on some external LDAP server providing the users including their tenant assignment.
|
||||
We'd like multi-tenancy to also work in environments where no such LDAP server is available.
|
||||
|
||||
## Decision Drivers
|
||||
|
||||
* Multi-tenancy must work without some existing external (as in not managed by us) LDAP server
|
||||
* keep the implementation effort low
|
||||
* allow integration with existing (de)provisioning systems
|
||||
|
||||
## Considered Options
|
||||
|
||||
### Use the auto-provisioning feature of КуСфера
|
||||
|
||||
We already have basic auto-provsioning features implemented in КуСфера.
|
||||
Currently this is not tenant-aware, but it could be extended to support that.
|
||||
This would require some changes in the way that the users are managed by the
|
||||
auto-proviosioning code.
|
||||
|
||||
The auto-provisioning code does currently use the "normal" graph API to create
|
||||
users. That API is not tenant-aware and would need to be significantly changed
|
||||
to support multi-tenancy. However currently there is no real need to put
|
||||
tenant-awareness into that API (and it would drive us even further a away from
|
||||
compatibility with the MS Graph API). We could also switch away from the Graph API
|
||||
for auto-provisioning and use some direct calls to the underlying LDAP server.
|
||||
|
||||
Also, using the auto-provisioning feature means that users are only created
|
||||
when they first login. This means it is not possible to share files with users that
|
||||
have not yet logged in. This is a significant limitation.
|
||||
|
||||
Also we don't currently have any de-provisioning features implemented.
|
||||
|
||||
### Use the existing Eudcation API of the Graph Service
|
||||
|
||||
We already implemented the Graph Education API in КуСфера (based on the MS Graph Education API).
|
||||
This, apart from the somewhat different naming, does already bring most of what is needed
|
||||
for provisioning users in a multi-tenant environment.
|
||||
|
||||
The customer would just need to hookup their existing (de)provisioning system to call the
|
||||
Education API to create/delete users and assign them to tenants (schools/classes).
|
||||
|
||||
The main drawback of this approach is that the customer needs to create some code to
|
||||
hookup their existing system to the Education API.
|
||||
|
||||
The main advantage is that it would give the customer much more control over the users' lifecycle.
|
||||
|
||||
## Decision Outcome
|
||||
|
||||
Use the existing Education API of the Graph Service.
|
||||
|
||||
* Allows integration with existing (de)provisioning systems
|
||||
* hopefully keeps the implementation effort low
|
||||
|
||||
Note: For now this means that the auto-provisioning feature will not be available for
|
||||
multi-tenant setups. We might want to revisit this in the future.
|
||||
|
||||
### Implementation Steps
|
||||
|
||||
* re-vive the existing Education API implementation and run it as a separate service
|
||||
* (maybe) allow to create tenants with a customer specified ID. The tenant id might also be
|
||||
part of the user's claims (provided by the customer's identity provider). It would be better
|
||||
if the tenant ids in our system match the tenant ids in the customer's identity provider.
|
||||
* For de-provisioning to work we need to implement a way to lookup users by an external ID as
|
||||
that is only unique identfier the customer's system knows for a user. While the MS Graph API
|
||||
already provides an `externalId` Attribute we don't currently support that on our APIs.
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
---
|
||||
title: "Discover OIDC Client configuration via WebFinger"
|
||||
---
|
||||
|
||||
* Status: accepted
|
||||
* Deciders: [@TheOneRing @kulmann @rhafer @dragotin]
|
||||
* Date: 2026-02-02
|
||||
|
||||
Reference: https://github.com/qsfera/server/pull/2072, https://github.com/qsfera-eu/desktop/issues/217
|
||||
|
||||
## Context and Problem Statement
|
||||
|
||||
Up to now our client applications used hard-coded OIDC client configurations.
|
||||
So it is not possible to change the client id that a client should use or the
|
||||
list of scopes that a client needs to request. This makes it hard to integrate
|
||||
КуСфера with various existing identity providers. For example:
|
||||
|
||||
- Authentik basically creates a different issuer URL for each client. As КуСфера
|
||||
can only work with a single issuer URL, all КуСфера clients need to use the
|
||||
same client id to work with Authentik.
|
||||
- Some IDPs (kanidm) are not able to work with user-supplied client ids. They generate
|
||||
client ids automatically and do not allow to specify them manually.
|
||||
- To make features like automatic role assignment work, clients need to request
|
||||
specific scopes, depending on which exact IDP is used.
|
||||
|
||||
## Decision Drivers
|
||||
|
||||
* Support broader set of IDPs
|
||||
* avoid any manual configuration adjustments on the client side
|
||||
|
||||
## Decision
|
||||
|
||||
Enhance the WebFinger service in КуСфера to provide platform-specific OIDC
|
||||
discovery, enabling clients to query for the correct OIDC `client_id` and
|
||||
`scopes` based on their application type (e.g., web, desktop, android, ios).
|
||||
|
||||
This is achieved by allowing an additional `platform` query parameter to be used
|
||||
when querying the WebFinger endpoint. The response will include the appropriate
|
||||
`client_id` and `scopes` in the `properties` section of the response.
|
||||
|
||||
This is implemented in a backward-compatible way, so existing clients that do not
|
||||
specify the `platform` parameter will continue to receive just the issuer information.
|
||||
|
||||
## Example
|
||||
|
||||
### Client Request
|
||||
|
||||
```
|
||||
GET /.well-known/webfinger?resource=https://cloud.qsfera.test&rel=http://openid.net/specs/connect/1.0/issuer&platform=desktop
|
||||
```
|
||||
|
||||
### Server Response
|
||||
|
||||
```json
|
||||
{
|
||||
"subject": "https://cloud.qsfera.test",
|
||||
"links": [{
|
||||
"rel": "http://openid.net/specs/connect/1.0/issuer",
|
||||
"href": "https://idp.example.com"
|
||||
}],
|
||||
"properties": {
|
||||
"http://qsfera.eu/ns/oidc/client_id": "desktop-client-id",
|
||||
"http://qsfera.eu/ns/oidc/scopes": ["openid", "profile", "email", "offline_access"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Server configuration (suggestion)
|
||||
|
||||
To configure the КуСфера server a couple of new config settings need to be introduced. This would
|
||||
be two new settings per client, e.g.:
|
||||
|
||||
|
||||
```
|
||||
WEBFINGER_ANDROID_OIDC_CLIENT_ID
|
||||
WEBFINGER_ANDROID_OIDC_CLIENT_SCOPES
|
||||
WEBFINGER_DESKTOP_OIDC_CLIENT_ID
|
||||
WEBFINGER_DESKTOP_OIDC_CLIENT_SCOPES
|
||||
WEBFINGER_IOS_OIDC_CLIENT_ID
|
||||
WEBFINGER_IOS_OIDC_CLIENT_SCOPES
|
||||
WEBFINGER_WEB_OIDC_CLIENT_ID
|
||||
WEBFINGER_WEB_OIDC_CLIENT_SCOPES
|
||||
```
|
||||
|
||||
Additionally for backwards compatibility the existing `WEB_OIDC_CLIENT_ID` and
|
||||
`WEB_OIDC_CLIENT_SCOPE` settings should be used as fallback for the `web`
|
||||
platform. Also we should make it easy to configure the same settings for all
|
||||
platforms at once by using `OC_OIDC_CLIENT_ID` and `OC_OIDC_CLIENT_SCOPE` as
|
||||
fallback for all platforms if the platform-specific settings are not set.
|
||||
@@ -0,0 +1,212 @@
|
||||
---
|
||||
title: "Inviting Guest users as fully integrated user in КуСфера"
|
||||
---
|
||||
|
||||
* Status: postponed
|
||||
* Deciders: []
|
||||
* Date: 2026-01-20
|
||||
|
||||
Reference: https://github.com/qsfera/server/issues/2111
|
||||
|
||||
## Important Disclaimer
|
||||
|
||||
The approach discussed here has been postponed (as of March, 2026) in favor
|
||||
of a different solution that does not require full-blown user-accounts in
|
||||
КуСфера. That approach is currently tracked here:
|
||||
https://github.com/qsfera/server/issues/2513
|
||||
|
||||
## Context and Problem statement
|
||||
|
||||
To allow collaboration with external Users (Users that don't yet have an
|
||||
account in the IDP, and might be external to the organization), it should
|
||||
be possible to invite "Guest Users" into an КуСфера instance.
|
||||
|
||||
## Requirements
|
||||
|
||||
- the audit trail of the external user accessing the resource needs to
|
||||
be maintained, that means sharing via a password protected public link
|
||||
is not sufficient as access to that one is tracked as if the creator
|
||||
of the link accessed the resource
|
||||
- external users need to be authenticated just like "normal" users, when
|
||||
accessing the shared resource (including the possibility to use 2FA)
|
||||
- the ability to invite external users is tied to a separate permission
|
||||
(e.g. "can invite guest users")
|
||||
- make it work with all (most) of the user-management configurations we support.
|
||||
The built-in IDP (lico) does not need to be supported.
|
||||
- avoid creating "Shadow IT" Infrastructure, e.g. we don't want to
|
||||
create/maintain a separate IDP instance just for Guest User that would
|
||||
allow bypassing corporate rules for Identity Management
|
||||
- the process of inviting a guest must can be asynchrounous, i.e. the user
|
||||
account of the guest user might not be created at the moment of
|
||||
creating the share/sending the invitaion as the whole process crosses
|
||||
multiple systems (КуСфера, Identity Management System, Email) and might
|
||||
even require manual steps.
|
||||
- It should be possible to "convert" a guest user into a "normal" user without
|
||||
the user loosing their shares.
|
||||
- Guest user invitations should have an expiration date, after which they can
|
||||
no longer be accepted.
|
||||
|
||||
|
||||
### Privileges of guest users
|
||||
|
||||
- guest users can not share or invite other users to a space or create public
|
||||
links. (primary focus of the feature is to provide a simple way to grant
|
||||
external, authorized access. anything else like resharing would undermine
|
||||
regular user accounts).
|
||||
- guestusers can use the desktop and mobile client to access their shares or spaces
|
||||
|
||||
|
||||
- all "normal" users are able to share with guest users, just as if they where "normal" users.
|
||||
|
||||
|
||||
## Questions still to be answered
|
||||
|
||||
- what's the life cycle of a guest user?
|
||||
- Who's responsible for deprovisioning?
|
||||
- Do guest users expire after a certain time?
|
||||
- Do we need to keep track of who invited whom and when? (not just in
|
||||
the audit log?)
|
||||
- What if the user already exists but used a different mail address in
|
||||
his account (e.g. sub-addressing?).
|
||||
|
||||
## Obstacles
|
||||
|
||||
### UserIDs
|
||||
|
||||
- Every user in КуСфера needs to have a userid assigned
|
||||
- Sharing, as many other features, needs that userid for storing the
|
||||
share (share service) and for assigning the grants on the shared
|
||||
resources (storage provider)
|
||||
- When an external IDP is used the generation of that userid is usually
|
||||
not in control of КуСфера (exception User-Autoprovisioning, or when
|
||||
the Provisioning/Education API is used). In that case, the userid is
|
||||
taken from a LDAP Attribute maintained in the external system
|
||||
|
||||
### Lots of identity management options
|
||||
|
||||
- КуСфера provides many different ways to consume user-accounts. Guest
|
||||
users are supposed to be working with all/most of them:
|
||||
- External IDP, with external LDAP service
|
||||
- External IDP, with manual provisioning via the
|
||||
Education/Provisioning APIs (to a local КуСфера specific LDAP
|
||||
service) - e.g. in multi-tenant setups
|
||||
- External IDP, with User-Autoprovisioning (also to a local КуСфера
|
||||
specific LDAP service)
|
||||
- everything in-between and outside of the above
|
||||
- Each of these options have different ways for user-provisioning and in
|
||||
the way userids are generated and managed
|
||||
|
||||
### How do we keep track of invitations?
|
||||
|
||||
- Completely rely on external system?
|
||||
- Track creation and acceptance of invitations somehow?
|
||||
- Do invitation expire at some point?
|
||||
|
||||
## Possible solutions
|
||||
|
||||
### Re-vitalize the PoC implementation of the invitations service and finalize it (<https://github.com/qsfera/server/blob/main/services/invitations/README.md>)
|
||||
|
||||
- Implements parts of the MSGraph Invitation Specification
|
||||
(<https://learn.microsoft.com/en-us/graph/api/resources/invitation?view=graph-rest-1.0>)
|
||||
- Currently there's just a single backend that allows creating users,
|
||||
using the Keycloak Admin API
|
||||
- As part of the user creation keycloak triggers an email to be sent to
|
||||
the invited user to get him to verify his email address and set a
|
||||
password. This is not really and invitation email.
|
||||
|
||||
#### Pros
|
||||
|
||||
- A partial implementation already exists
|
||||
- no shadow IT
|
||||
|
||||
#### Cons
|
||||
|
||||
- while the emails sent by keycloak can be themed. There is no way
|
||||
to add custom content, like: "you've being invited by user X to
|
||||
access resource Y"
|
||||
- the keycloak admin API does not return the password reset link in
|
||||
the response, so we can't use that to send a custom email
|
||||
- the keycloak implementation is not a real "user invitation"
|
||||
workflow, the user experience for the invited user is not ideal
|
||||
- The workflow likely only works with a limited set of setups.
|
||||
(Specifically: a keycloak that is able to write into a connected
|
||||
LDAP database, that КуСфера can consume)
|
||||
- As the invitations are not really tracked, e.g. we don't really
|
||||
"know" if an invitation was accepted
|
||||
- Requires direct access to the Identity Management System
|
||||
|
||||
### Invitation Service + support for pending shares in the share manager
|
||||
|
||||
- Create some form in invitation manager and provide tools/documentation
|
||||
for customers to hook that up with their Identity Management System
|
||||
- User's with the "right" privileges are able to create invitations,
|
||||
invitations get a unique identifier. Other data maintained on the
|
||||
invitation:
|
||||
- Invited user's email address
|
||||
- Invited user's userid (once the user account was provisioned)
|
||||
- Inviting user's userid
|
||||
- Creation timestamp
|
||||
- Invitation State (Pending, Accepted, …)
|
||||
- (more probably)
|
||||
- our sharing API
|
||||
('graph/v1beta1/drives/{drive-id}/items/{item-id}/invite') is enhanced
|
||||
to allow creating shares that target an invitation as the share
|
||||
recipient. (That share would only be persisted in the 'shares' service
|
||||
and would not yet crate any grants on the filesystem, or send out
|
||||
sharing notifications). (Requires changes to the CS3 sharing APIs)
|
||||
- A middleware (specific to the Identity Management System) is
|
||||
"informed" (e.g. via web hooks or a message queue) when a new
|
||||
invitation is created. That middleware is responsible for provisioning
|
||||
the user account of the guest user. Whatever this process looks like
|
||||
it completely up to the middleware (maybe it triggers some invitation
|
||||
workflow or it could just even open a support ticket with the IDP
|
||||
admin)
|
||||
- once the user is provisioned the middleware calls back into our
|
||||
invitations service,marks the invitation as "accepted" and provides
|
||||
the "userid" of the guest user. The invitations service then triggers
|
||||
the "pending" shares to be processes, which causes the filesystem
|
||||
grants to be written and notifications to be send out to the guest
|
||||
user.
|
||||
- We'd provide a reference implementation of that middleware, that works
|
||||
with keycloak
|
||||
|
||||
#### Pros
|
||||
|
||||
- Agnostic to whatever Identity Management System is used
|
||||
- We have an audittrail about who was invited by whom at what point
|
||||
in time
|
||||
- no shadow IT
|
||||
|
||||
#### Cons
|
||||
|
||||
- somewhat complex
|
||||
- likely requires changes to the CS3 APIs
|
||||
|
||||
#### Implementation Obstacles
|
||||
|
||||
- Permissions on spaces are currently not tracked in the share
|
||||
manager, the are purely managed via grants. So currently the share
|
||||
manager service currently does not know anything about (invited)
|
||||
users being assigned to spaces
|
||||
|
||||
## Additional thoughts
|
||||
|
||||
If КуСфера were responsible for allocating the UserIDs of all users
|
||||
the solution sketch above would likely loose some of its complexity. We
|
||||
would "roll" the userid for the invited user already when creating the invite.
|
||||
That would allow to skip the step of creating a "pending" Share with an
|
||||
invitation assigned. As we have an ID already, we could just create a "normal"
|
||||
share and even populate the grants on the filesystem for that share (or space)
|
||||
|
||||
We've been pondering on the idea of making КуСфера manage all UserIDs
|
||||
for quite a while as it would have some additional benefits for the
|
||||
whole user management story.
|
||||
|
||||
- We wouldn't rely anymore on the external Identity Management system to
|
||||
provide a unique id with certain properties. Ideally the only unique
|
||||
thing we'd need from the external system is the `iss` and `sub`
|
||||
claims of the IDP and those are required by the OIDC standards.
|
||||
|
||||
It could be worth to spend some time on figuring out a migration path
|
||||
towards such a solution, before spending resources on a complex guest
|
||||
features implementation.
|
||||
@@ -0,0 +1,91 @@
|
||||
# Architecture Decision Records (ADRs)
|
||||
|
||||
## Purpose
|
||||
|
||||
This folder contains Architecture Decision Records (ADRs) for the КуСфера related topics.
|
||||
ADRs capture important architectural decisions, their context, alternatives, and rationale.
|
||||
|
||||
They help us:
|
||||
|
||||
- Document the reasoning behind significant technical choices.
|
||||
- Share knowledge and context with current and future team members.
|
||||
- Ensure transparency and continuity in our architectural evolution.
|
||||
|
||||
## Why Use ADRs?
|
||||
|
||||
ADRs provide a structured way to record, discuss, and find architectural decisions over time.
|
||||
They make it easier to:
|
||||
|
||||
- Understand why certain approaches were chosen.
|
||||
- Avoid revisiting previous discussions without context.
|
||||
- Onboard new contributors efficiently.
|
||||
|
||||
## When to Create an ADR
|
||||
|
||||
Not every technical or architectural decision needs a dedicated ADR.
|
||||
Use an ADR to document decisions which are significant, such as:
|
||||
|
||||
* It substantially affects the architecture, design, or direction of КуСфера.
|
||||
* It involves trade-offs between multiple options.
|
||||
* It needs Team consensus or input from multiple stakeholders.
|
||||
|
||||
## Writing ADRs
|
||||
|
||||
- **Location**: Store all ADRs as Markdown files in this folder.
|
||||
- **Format**: Use [Markdown](https://commonmark.org/).
|
||||
- **Naming**: Adhere to the naming convention, e.g., `0001-descriptive-title.md`.
|
||||
|
||||
### ADR Template
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: "Some Descriptive Title"
|
||||
---
|
||||
|
||||
* Status: proposed / accepted / deprecated / superseded
|
||||
* Deciders: [@user1, @user2]
|
||||
* Date: YYYY-MM-DD
|
||||
|
||||
Reference: (link to relevant epic, story, issue)
|
||||
|
||||
## Context and Problem Statement
|
||||
|
||||
Describe the background and why this decision is needed.
|
||||
|
||||
## Decision Drivers
|
||||
|
||||
Describe the criteria that explains why this decision has to be made.
|
||||
|
||||
## Considered Options
|
||||
|
||||
Describe single or multiple options that were considered or could be considered.
|
||||
|
||||
## Decision Outcome
|
||||
|
||||
Describe the chosen option and why it was selected.
|
||||
|
||||
### Implementation Steps
|
||||
|
||||
Describe the steps needed to implement the decision.
|
||||
```
|
||||
|
||||
## Process
|
||||
|
||||
### New ADRs
|
||||
|
||||
1. Write a new ADR as a Markdown file.
|
||||
2. Submit it via pull request for review.
|
||||
3. Decision is made collaboratively, details will be discussed in the PR, which can lead to further changes.
|
||||
4. Update the ADR status once a decision is reached.
|
||||
5. Reference ADRs in code, documentation, or issues where relevant.
|
||||
|
||||
### Updating ADRs
|
||||
|
||||
1. If an ADR needs to be updated, create a new ADR that references the original.
|
||||
2. Follow the same process as for new ADRs.
|
||||
3. Once accepted, update the status of the original ADR and reference that new ADR.
|
||||
|
||||
## References
|
||||
|
||||
- [ADR GitHub Template](https://github.com/joelparkerhenderson/architecture_decision_record)
|
||||
- [Wikipedia on ADRs](https://en.wikipedia.org/wiki/Architectural_decision)
|
||||
Reference in New Issue
Block a user