feat: archive a project instead of deleting it

The owner archives a finished project (archiveProject, POST
/projects/{project}/archive) and brings it back (unarchive). While
archived it stays readable, managers still read its rules and webhooks,
but no command changes it: contributing and managing checks refuse with
422, votes and public proposals too, and automations do not run. The web
shows a read-only notice on every page of it (with «Desarchivar» for the
owner), hides what edits, marks it on the home page and lists it last.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-15 15:46:22 +02:00
parent e598f76e1c
commit 4acf629106
42 changed files with 1057 additions and 14 deletions

View File

@@ -527,6 +527,7 @@ export type ProjectFieldsFragment = {
description: string | null;
isPublic: boolean;
acceptsProposals: boolean;
archivedAt: string | null;
updatedAt: string;
version: number;
owner: { id: string; name: string };
@@ -1522,6 +1523,7 @@ export type MyProjectsQuery = {
description: string | null;
isPublic: boolean;
acceptsProposals: boolean;
archivedAt: string | null;
updatedAt: string;
version: number;
owner: { id: string; name: string };
@@ -1573,6 +1575,7 @@ export type ProjectQuery = {
description: string | null;
isPublic: boolean;
acceptsProposals: boolean;
archivedAt: string | null;
updatedAt: string;
version: number;
owner: { id: string; name: string };
@@ -1734,6 +1737,7 @@ export type PublicProjectsQuery = {
description: string | null;
isPublic: boolean;
acceptsProposals: boolean;
archivedAt: string | null;
updatedAt: string;
version: number;
owner: { id: string; name: string };
@@ -1781,6 +1785,22 @@ export type UpdateProjectMutation = {
updateProject: { id: string; key: string | null; version: number };
};
export type ArchiveProjectMutationVariables = Exact<{
projectId: string;
}>;
export type ArchiveProjectMutation = {
archiveProject: { id: string; key: string | null; version: number };
};
export type UnarchiveProjectMutationVariables = Exact<{
projectId: string;
}>;
export type UnarchiveProjectMutation = {
unarchiveProject: { id: string; key: string | null; version: number };
};
export type DeleteProjectMutationVariables = Exact<{
projectId: string;
confirmKey: string;
@@ -2410,6 +2430,7 @@ export type ProjectChangedSubscription = {
description: string | null;
isPublic: boolean;
acceptsProposals: boolean;
archivedAt: string | null;
updatedAt: string;
version: number;
owner: { id: string; name: string };
@@ -2464,6 +2485,7 @@ export type MyProjectsChangedSubscription = {
description: string | null;
isPublic: boolean;
acceptsProposals: boolean;
archivedAt: string | null;
updatedAt: string;
version: number;
owner: { id: string; name: string };
@@ -2730,6 +2752,7 @@ export const ProjectFieldsFragmentDoc = {
{ kind: 'Field', name: { kind: 'Name', value: 'description' } },
{ kind: 'Field', name: { kind: 'Name', value: 'isPublic' } },
{ kind: 'Field', name: { kind: 'Name', value: 'acceptsProposals' } },
{ kind: 'Field', name: { kind: 'Name', value: 'archivedAt' } },
{ kind: 'Field', name: { kind: 'Name', value: 'updatedAt' } },
{ kind: 'Field', name: { kind: 'Name', value: 'version' } },
{
@@ -9475,6 +9498,7 @@ export const MyProjectsDocument = {
{ kind: 'Field', name: { kind: 'Name', value: 'description' } },
{ kind: 'Field', name: { kind: 'Name', value: 'isPublic' } },
{ kind: 'Field', name: { kind: 'Name', value: 'acceptsProposals' } },
{ kind: 'Field', name: { kind: 'Name', value: 'archivedAt' } },
{ kind: 'Field', name: { kind: 'Name', value: 'updatedAt' } },
{ kind: 'Field', name: { kind: 'Name', value: 'version' } },
{
@@ -9722,6 +9746,7 @@ export const ProjectDocument = {
{ kind: 'Field', name: { kind: 'Name', value: 'description' } },
{ kind: 'Field', name: { kind: 'Name', value: 'isPublic' } },
{ kind: 'Field', name: { kind: 'Name', value: 'acceptsProposals' } },
{ kind: 'Field', name: { kind: 'Name', value: 'archivedAt' } },
{ kind: 'Field', name: { kind: 'Name', value: 'updatedAt' } },
{ kind: 'Field', name: { kind: 'Name', value: 'version' } },
{
@@ -10820,6 +10845,7 @@ export const PublicProjectsDocument = {
{ kind: 'Field', name: { kind: 'Name', value: 'description' } },
{ kind: 'Field', name: { kind: 'Name', value: 'isPublic' } },
{ kind: 'Field', name: { kind: 'Name', value: 'acceptsProposals' } },
{ kind: 'Field', name: { kind: 'Name', value: 'archivedAt' } },
{ kind: 'Field', name: { kind: 'Name', value: 'updatedAt' } },
{ kind: 'Field', name: { kind: 'Name', value: 'version' } },
{
@@ -11057,6 +11083,146 @@ export const UpdateProjectDocument = {
UpdateProjectMutation,
UpdateProjectMutationVariables
>;
export const ArchiveProjectDocument = {
kind: 'Document',
definitions: [
{
kind: 'OperationDefinition',
operation: 'mutation',
name: { kind: 'Name', value: 'ArchiveProject' },
variableDefinitions: [
{
kind: 'VariableDefinition',
variable: {
kind: 'Variable',
name: { kind: 'Name', value: 'projectId' },
},
type: {
kind: 'NonNullType',
type: { kind: 'NamedType', name: { kind: 'Name', value: 'ID' } },
},
},
],
selectionSet: {
kind: 'SelectionSet',
selections: [
{
kind: 'Field',
name: { kind: 'Name', value: 'archiveProject' },
arguments: [
{
kind: 'Argument',
name: { kind: 'Name', value: 'projectId' },
value: {
kind: 'Variable',
name: { kind: 'Name', value: 'projectId' },
},
},
],
selectionSet: {
kind: 'SelectionSet',
selections: [
{
kind: 'FragmentSpread',
name: { kind: 'Name', value: 'CommandResultFields' },
},
],
},
},
],
},
},
{
kind: 'FragmentDefinition',
name: { kind: 'Name', value: 'CommandResultFields' },
typeCondition: {
kind: 'NamedType',
name: { kind: 'Name', value: 'CommandResult' },
},
selectionSet: {
kind: 'SelectionSet',
selections: [
{ kind: 'Field', name: { kind: 'Name', value: 'id' } },
{ kind: 'Field', name: { kind: 'Name', value: 'key' } },
{ kind: 'Field', name: { kind: 'Name', value: 'version' } },
],
},
},
],
} as unknown as DocumentNode<
ArchiveProjectMutation,
ArchiveProjectMutationVariables
>;
export const UnarchiveProjectDocument = {
kind: 'Document',
definitions: [
{
kind: 'OperationDefinition',
operation: 'mutation',
name: { kind: 'Name', value: 'UnarchiveProject' },
variableDefinitions: [
{
kind: 'VariableDefinition',
variable: {
kind: 'Variable',
name: { kind: 'Name', value: 'projectId' },
},
type: {
kind: 'NonNullType',
type: { kind: 'NamedType', name: { kind: 'Name', value: 'ID' } },
},
},
],
selectionSet: {
kind: 'SelectionSet',
selections: [
{
kind: 'Field',
name: { kind: 'Name', value: 'unarchiveProject' },
arguments: [
{
kind: 'Argument',
name: { kind: 'Name', value: 'projectId' },
value: {
kind: 'Variable',
name: { kind: 'Name', value: 'projectId' },
},
},
],
selectionSet: {
kind: 'SelectionSet',
selections: [
{
kind: 'FragmentSpread',
name: { kind: 'Name', value: 'CommandResultFields' },
},
],
},
},
],
},
},
{
kind: 'FragmentDefinition',
name: { kind: 'Name', value: 'CommandResultFields' },
typeCondition: {
kind: 'NamedType',
name: { kind: 'Name', value: 'CommandResult' },
},
selectionSet: {
kind: 'SelectionSet',
selections: [
{ kind: 'Field', name: { kind: 'Name', value: 'id' } },
{ kind: 'Field', name: { kind: 'Name', value: 'key' } },
{ kind: 'Field', name: { kind: 'Name', value: 'version' } },
],
},
},
],
} as unknown as DocumentNode<
UnarchiveProjectMutation,
UnarchiveProjectMutationVariables
>;
export const DeleteProjectDocument = {
kind: 'Document',
definitions: [
@@ -14206,6 +14372,7 @@ export const ProjectChangedDocument = {
{ kind: 'Field', name: { kind: 'Name', value: 'description' } },
{ kind: 'Field', name: { kind: 'Name', value: 'isPublic' } },
{ kind: 'Field', name: { kind: 'Name', value: 'acceptsProposals' } },
{ kind: 'Field', name: { kind: 'Name', value: 'archivedAt' } },
{ kind: 'Field', name: { kind: 'Name', value: 'updatedAt' } },
{ kind: 'Field', name: { kind: 'Name', value: 'version' } },
{
@@ -14440,6 +14607,7 @@ export const MyProjectsChangedDocument = {
{ kind: 'Field', name: { kind: 'Name', value: 'description' } },
{ kind: 'Field', name: { kind: 'Name', value: 'isPublic' } },
{ kind: 'Field', name: { kind: 'Name', value: 'acceptsProposals' } },
{ kind: 'Field', name: { kind: 'Name', value: 'archivedAt' } },
{ kind: 'Field', name: { kind: 'Name', value: 'updatedAt' } },
{ kind: 'Field', name: { kind: 'Name', value: 'version' } },
{