trueppm-api 0.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- trueppm_api/__init__.py +27 -0
- trueppm_api/apps/access/__init__.py +0 -0
- trueppm_api/apps/access/apps.py +19 -0
- trueppm_api/apps/access/groups.py +518 -0
- trueppm_api/apps/access/management/__init__.py +0 -0
- trueppm_api/apps/access/management/commands/__init__.py +0 -0
- trueppm_api/apps/access/management/commands/create_admin.py +346 -0
- trueppm_api/apps/access/management/commands/migrate_locked.py +96 -0
- trueppm_api/apps/access/management/commands/revoke_api_tokens.py +483 -0
- trueppm_api/apps/access/migrations/0001_initial.py +61 -0
- trueppm_api/apps/access/migrations/0001_squashed_0012_programmembership_role_title.py +184 -0
- trueppm_api/apps/access/migrations/0002_alter_projectmembership_id.py +29 -0
- trueppm_api/apps/access/migrations/0003_projectmembership_soft_delete.py +24 -0
- trueppm_api/apps/access/migrations/0004_alter_projectmembership_role.py +34 -0
- trueppm_api/apps/access/migrations/0005_program_entity_and_membership.py +76 -0
- trueppm_api/apps/access/migrations/0006_role_ordinal_spacing.py +113 -0
- trueppm_api/apps/access/migrations/0007_projectmembership_joined_at_and_more.py +35 -0
- trueppm_api/apps/access/migrations/0008_projectmembership_source_group.py +25 -0
- trueppm_api/apps/access/migrations/0009_projectmembership_pm_proj_serverver_idx.py +20 -0
- trueppm_api/apps/access/migrations/0010_programmembership_joined_at_and_more.py +38 -0
- trueppm_api/apps/access/migrations/0011_alter_programmembership_unique_together_and_more.py +36 -0
- trueppm_api/apps/access/migrations/0012_programmembership_role_title.py +17 -0
- trueppm_api/apps/access/migrations/0013_squashed_0019_release_0_4.py +302 -0
- trueppm_api/apps/access/migrations/0013_userdefinedmentiongroup.py +82 -0
- trueppm_api/apps/access/migrations/0014_programmembership_progm_serverver_idx.py +19 -0
- trueppm_api/apps/access/migrations/0015_programuserdefinedmentiongroup.py +86 -0
- trueppm_api/apps/access/migrations/0016_externalstakeholder.py +67 -0
- trueppm_api/apps/access/migrations/0017_viewer_ordinal_one.py +143 -0
- trueppm_api/apps/access/migrations/0018_programmembership_sync_seq_and_more.py +52 -0
- trueppm_api/apps/access/migrations/0019_programmembership_reinstated_at_and_more.py +22 -0
- trueppm_api/apps/access/migrations/__init__.py +0 -0
- trueppm_api/apps/access/minter_role.py +38 -0
- trueppm_api/apps/access/models.py +588 -0
- trueppm_api/apps/access/permissions.py +3263 -0
- trueppm_api/apps/access/serializers.py +1007 -0
- trueppm_api/apps/access/services.py +878 -0
- trueppm_api/apps/access/signals.py +171 -0
- trueppm_api/apps/access/tasks.py +50 -0
- trueppm_api/apps/access/throttles.py +96 -0
- trueppm_api/apps/access/urls.py +191 -0
- trueppm_api/apps/access/views.py +1965 -0
- trueppm_api/apps/agents/__init__.py +6 -0
- trueppm_api/apps/agents/apps.py +11 -0
- trueppm_api/apps/agents/canonical.py +73 -0
- trueppm_api/apps/agents/deferred.py +108 -0
- trueppm_api/apps/agents/management/__init__.py +0 -0
- trueppm_api/apps/agents/management/commands/__init__.py +0 -0
- trueppm_api/apps/agents/management/commands/audit_prune.py +137 -0
- trueppm_api/apps/agents/management/commands/audit_verify.py +101 -0
- trueppm_api/apps/agents/middleware.py +44 -0
- trueppm_api/apps/agents/migrations/0001_initial.py +231 -0
- trueppm_api/apps/agents/migrations/0001_squashed_0003_release_0_4.py +344 -0
- trueppm_api/apps/agents/migrations/0002_agentactioncheckpoint.py +71 -0
- trueppm_api/apps/agents/migrations/0003_agentactionrefusaldetail.py +58 -0
- trueppm_api/apps/agents/migrations/__init__.py +0 -0
- trueppm_api/apps/agents/models.py +371 -0
- trueppm_api/apps/agents/refusal.py +103 -0
- trueppm_api/apps/agents/serializers.py +85 -0
- trueppm_api/apps/agents/services.py +397 -0
- trueppm_api/apps/agents/signals.py +30 -0
- trueppm_api/apps/agents/urls.py +15 -0
- trueppm_api/apps/agents/views.py +109 -0
- trueppm_api/apps/csvimport/__init__.py +12 -0
- trueppm_api/apps/csvimport/apps.py +11 -0
- trueppm_api/apps/csvimport/mapping.py +363 -0
- trueppm_api/apps/csvimport/migrations/0001_initial.py +74 -0
- trueppm_api/apps/csvimport/migrations/0001_squashed_0003_release_0_4.py +90 -0
- trueppm_api/apps/csvimport/migrations/0002_schedule_outline_batch_operations.py +37 -0
- trueppm_api/apps/csvimport/migrations/0003_csvimportrequest_date_order_and_more.py +26 -0
- trueppm_api/apps/csvimport/migrations/__init__.py +0 -0
- trueppm_api/apps/csvimport/models.py +111 -0
- trueppm_api/apps/csvimport/parser.py +1825 -0
- trueppm_api/apps/csvimport/services.py +48 -0
- trueppm_api/apps/csvimport/tasks.py +459 -0
- trueppm_api/apps/csvimport/template.py +37 -0
- trueppm_api/apps/csvimport/urls.py +50 -0
- trueppm_api/apps/csvimport/views.py +793 -0
- trueppm_api/apps/history/__init__.py +0 -0
- trueppm_api/apps/history/apps.py +12 -0
- trueppm_api/apps/history/changelog.py +359 -0
- trueppm_api/apps/history/diff_policy.py +178 -0
- trueppm_api/apps/history/serializers.py +104 -0
- trueppm_api/apps/history/signals.py +82 -0
- trueppm_api/apps/history/tasks.py +105 -0
- trueppm_api/apps/history/urls.py +38 -0
- trueppm_api/apps/history/views.py +443 -0
- trueppm_api/apps/idempotency/__init__.py +0 -0
- trueppm_api/apps/idempotency/apps.py +11 -0
- trueppm_api/apps/idempotency/migrations/0001_initial.py +71 -0
- trueppm_api/apps/idempotency/migrations/__init__.py +0 -0
- trueppm_api/apps/idempotency/mixins.py +226 -0
- trueppm_api/apps/idempotency/models.py +75 -0
- trueppm_api/apps/idempotency/tasks.py +61 -0
- trueppm_api/apps/integrations/__init__.py +13 -0
- trueppm_api/apps/integrations/apps.py +59 -0
- trueppm_api/apps/integrations/connections.py +806 -0
- trueppm_api/apps/integrations/encryption.py +92 -0
- trueppm_api/apps/integrations/external_sources.py +863 -0
- trueppm_api/apps/integrations/git_automation_services.py +231 -0
- trueppm_api/apps/integrations/git_webhook_auth.py +243 -0
- trueppm_api/apps/integrations/http.py +597 -0
- trueppm_api/apps/integrations/me_work.py +218 -0
- trueppm_api/apps/integrations/migrations/0001_initial.py +64 -0
- trueppm_api/apps/integrations/migrations/0001_squashed_0006_tasklink_description_tasklink_preview_type_and_more.py +187 -0
- trueppm_api/apps/integrations/migrations/0002_tasklink.py +67 -0
- trueppm_api/apps/integrations/migrations/0003_tasklink_tasklink_serverver_idx.py +17 -0
- trueppm_api/apps/integrations/migrations/0004_tasklink_custom_title_tasklink_labels.py +25 -0
- trueppm_api/apps/integrations/migrations/0005_boardautomation.py +56 -0
- trueppm_api/apps/integrations/migrations/0006_tasklink_description_tasklink_preview_type_and_more.py +40 -0
- trueppm_api/apps/integrations/migrations/0007_squashed_0014_release_0_4.py +225 -0
- trueppm_api/apps/integrations/migrations/0007_tasklink_created_at.py +23 -0
- trueppm_api/apps/integrations/migrations/0008_integrationcredential_config_externalworkitem.py +66 -0
- trueppm_api/apps/integrations/migrations/0009_externalsyncrequest_and_more.py +96 -0
- trueppm_api/apps/integrations/migrations/0010_externalworkitem_due_date.py +17 -0
- trueppm_api/apps/integrations/migrations/0011_tasklink_sync_seq_tasklink_tasklink_syncseq_idx.py +22 -0
- trueppm_api/apps/integrations/migrations/0012_boardautomation_last_delivery_at_and_more.py +42 -0
- trueppm_api/apps/integrations/migrations/0013_externalsyncrequest_attempt_count_and_more.py +26 -0
- trueppm_api/apps/integrations/migrations/0014_tasklink_created_by.py +27 -0
- trueppm_api/apps/integrations/migrations/__init__.py +0 -0
- trueppm_api/apps/integrations/models.py +635 -0
- trueppm_api/apps/integrations/notification_channels.py +57 -0
- trueppm_api/apps/integrations/opengraph.py +229 -0
- trueppm_api/apps/integrations/outgoing.py +201 -0
- trueppm_api/apps/integrations/providers.py +528 -0
- trueppm_api/apps/integrations/registry.py +345 -0
- trueppm_api/apps/integrations/serializers.py +453 -0
- trueppm_api/apps/integrations/services.py +171 -0
- trueppm_api/apps/integrations/tasks.py +734 -0
- trueppm_api/apps/integrations/throttles.py +165 -0
- trueppm_api/apps/integrations/urls.py +77 -0
- trueppm_api/apps/integrations/views.py +1158 -0
- trueppm_api/apps/jiraimport/__init__.py +8 -0
- trueppm_api/apps/jiraimport/apps.py +11 -0
- trueppm_api/apps/jiraimport/migrations/0001_initial.py +72 -0
- trueppm_api/apps/jiraimport/migrations/__init__.py +0 -0
- trueppm_api/apps/jiraimport/models.py +70 -0
- trueppm_api/apps/jiraimport/parser.py +350 -0
- trueppm_api/apps/jiraimport/services.py +46 -0
- trueppm_api/apps/jiraimport/tasks.py +280 -0
- trueppm_api/apps/jiraimport/urls.py +15 -0
- trueppm_api/apps/jiraimport/views.py +153 -0
- trueppm_api/apps/msproject/__init__.py +0 -0
- trueppm_api/apps/msproject/apps.py +11 -0
- trueppm_api/apps/msproject/dataclasses.py +153 -0
- trueppm_api/apps/msproject/exporter.py +551 -0
- trueppm_api/apps/msproject/extended_attributes.py +77 -0
- trueppm_api/apps/msproject/importer.py +1095 -0
- trueppm_api/apps/msproject/migrations/0001_import_request.py +77 -0
- trueppm_api/apps/msproject/migrations/0001_squashed_0002_importrequest_creates_project.py +80 -0
- trueppm_api/apps/msproject/migrations/0002_importrequest_creates_project.py +15 -0
- trueppm_api/apps/msproject/migrations/__init__.py +0 -0
- trueppm_api/apps/msproject/models.py +81 -0
- trueppm_api/apps/msproject/parser.py +1276 -0
- trueppm_api/apps/msproject/serializers.py +136 -0
- trueppm_api/apps/msproject/services.py +58 -0
- trueppm_api/apps/msproject/tasks.py +439 -0
- trueppm_api/apps/msproject/urls.py +39 -0
- trueppm_api/apps/msproject/views.py +531 -0
- trueppm_api/apps/notifications/__init__.py +7 -0
- trueppm_api/apps/notifications/apps.py +15 -0
- trueppm_api/apps/notifications/backfill.py +79 -0
- trueppm_api/apps/notifications/categories.py +112 -0
- trueppm_api/apps/notifications/delivery_limits.py +258 -0
- trueppm_api/apps/notifications/digests.py +462 -0
- trueppm_api/apps/notifications/email_backend.py +350 -0
- trueppm_api/apps/notifications/email_health.py +128 -0
- trueppm_api/apps/notifications/migrations/0001_initial.py +207 -0
- trueppm_api/apps/notifications/migrations/0001_squashed_0006_notification_task.py +299 -0
- trueppm_api/apps/notifications/migrations/0002_project_notification_preference.py +67 -0
- trueppm_api/apps/notifications/migrations/0003_projectnotificationpreference_paused.py +17 -0
- trueppm_api/apps/notifications/migrations/0004_clean_unknown_matrix_keys.py +30 -0
- trueppm_api/apps/notifications/migrations/0005_notification_body_notification_event_type_and_more.py +27 -0
- trueppm_api/apps/notifications/migrations/0006_notification_task.py +25 -0
- trueppm_api/apps/notifications/migrations/0007_squashed_0011_release_0_4.py +204 -0
- trueppm_api/apps/notifications/migrations/0007_workspaceemailsettings.py +80 -0
- trueppm_api/apps/notifications/migrations/0008_notification_snoozed_until.py +17 -0
- trueppm_api/apps/notifications/migrations/0009_usernotificationsettings.py +43 -0
- trueppm_api/apps/notifications/migrations/0010_projectnotificationpreference_schema_version.py +20 -0
- trueppm_api/apps/notifications/migrations/0011_usernotificationsettings_digest_hour_and_more.py +96 -0
- trueppm_api/apps/notifications/migrations/__init__.py +0 -0
- trueppm_api/apps/notifications/models.py +1148 -0
- trueppm_api/apps/notifications/receivers.py +155 -0
- trueppm_api/apps/notifications/schema_migrations.py +56 -0
- trueppm_api/apps/notifications/serializers.py +1094 -0
- trueppm_api/apps/notifications/services.py +1489 -0
- trueppm_api/apps/notifications/tasks.py +762 -0
- trueppm_api/apps/notifications/throttles.py +98 -0
- trueppm_api/apps/notifications/urls.py +97 -0
- trueppm_api/apps/notifications/views.py +919 -0
- trueppm_api/apps/observability/__init__.py +0 -0
- trueppm_api/apps/observability/apps.py +31 -0
- trueppm_api/apps/observability/logging.py +213 -0
- trueppm_api/apps/observability/migrations/0001_initial.py +35 -0
- trueppm_api/apps/observability/migrations/0001_squashed_0003_alter_purgerun_trigger.py +154 -0
- trueppm_api/apps/observability/migrations/0002_purgerun_retentionpolicy_retentionschedule.py +131 -0
- trueppm_api/apps/observability/migrations/0003_alter_purgerun_trigger.py +21 -0
- trueppm_api/apps/observability/migrations/0004_alter_retentionpolicy_key.py +28 -0
- trueppm_api/apps/observability/migrations/__init__.py +0 -0
- trueppm_api/apps/observability/models.py +141 -0
- trueppm_api/apps/observability/otel/__init__.py +45 -0
- trueppm_api/apps/observability/otel/attributes.py +247 -0
- trueppm_api/apps/observability/otel/export_health.py +533 -0
- trueppm_api/apps/observability/otel/instrumentation.py +351 -0
- trueppm_api/apps/observability/otel/metrics.py +566 -0
- trueppm_api/apps/observability/otel/provider.py +511 -0
- trueppm_api/apps/observability/otel/request_attributes.py +204 -0
- trueppm_api/apps/observability/purge_registry.py +124 -0
- trueppm_api/apps/observability/retention.py +139 -0
- trueppm_api/apps/observability/selectors.py +993 -0
- trueppm_api/apps/observability/serializers.py +142 -0
- trueppm_api/apps/observability/services.py +407 -0
- trueppm_api/apps/observability/tasks.py +266 -0
- trueppm_api/apps/observability/urls.py +27 -0
- trueppm_api/apps/observability/views.py +537 -0
- trueppm_api/apps/profiles/__init__.py +0 -0
- trueppm_api/apps/profiles/apps.py +15 -0
- trueppm_api/apps/profiles/constants.py +54 -0
- trueppm_api/apps/profiles/migrations/0001_initial.py +55 -0
- trueppm_api/apps/profiles/migrations/0001_squashed_0004_userprofile_role_context.py +125 -0
- trueppm_api/apps/profiles/migrations/0002_userprofile_hidden_views.py +17 -0
- trueppm_api/apps/profiles/migrations/0003_projectvisit.py +63 -0
- trueppm_api/apps/profiles/migrations/0004_userprofile_role_context.py +26 -0
- trueppm_api/apps/profiles/migrations/0005_squashed_0009_release_0_4.py +128 -0
- trueppm_api/apps/profiles/migrations/0005_userprofile_schedule_in_deliver.py +20 -0
- trueppm_api/apps/profiles/migrations/0006_userprofile_date_format_userprofile_timezone.py +36 -0
- trueppm_api/apps/profiles/migrations/0007_userpin.py +91 -0
- trueppm_api/apps/profiles/migrations/0008_remove_userprofile_schedule_in_deliver.py +71 -0
- trueppm_api/apps/profiles/migrations/0009_auth_user_email_upper_idx.py +81 -0
- trueppm_api/apps/profiles/migrations/__init__.py +0 -0
- trueppm_api/apps/profiles/models.py +276 -0
- trueppm_api/apps/profiles/serializers.py +199 -0
- trueppm_api/apps/profiles/services.py +541 -0
- trueppm_api/apps/profiles/views.py +124 -0
- trueppm_api/apps/projects/__init__.py +0 -0
- trueppm_api/apps/projects/actual_date_rules.py +163 -0
- trueppm_api/apps/projects/amend.py +133 -0
- trueppm_api/apps/projects/apps.py +38 -0
- trueppm_api/apps/projects/asset_feed.py +459 -0
- trueppm_api/apps/projects/asset_views.py +317 -0
- trueppm_api/apps/projects/attachment_policy.py +278 -0
- trueppm_api/apps/projects/authentication.py +458 -0
- trueppm_api/apps/projects/backfill.py +459 -0
- trueppm_api/apps/projects/backlog_services.py +324 -0
- trueppm_api/apps/projects/backlog_views.py +302 -0
- trueppm_api/apps/projects/batch_operation_views.py +264 -0
- trueppm_api/apps/projects/blocker_services.py +510 -0
- trueppm_api/apps/projects/board_activity.py +462 -0
- trueppm_api/apps/projects/board_activity_views.py +186 -0
- trueppm_api/apps/projects/board_lanes.py +134 -0
- trueppm_api/apps/projects/bulk_settings.py +194 -0
- trueppm_api/apps/projects/bundled_templates.py +215 -0
- trueppm_api/apps/projects/calendar_settings.py +180 -0
- trueppm_api/apps/projects/ceremony_views.py +244 -0
- trueppm_api/apps/projects/commit_moment.py +212 -0
- trueppm_api/apps/projects/config_notice.py +1330 -0
- trueppm_api/apps/projects/custom_field_values.py +266 -0
- trueppm_api/apps/projects/decisions_services.py +132 -0
- trueppm_api/apps/projects/decisions_views.py +97 -0
- trueppm_api/apps/projects/estimation_scale.py +126 -0
- trueppm_api/apps/projects/export_bundle.py +423 -0
- trueppm_api/apps/projects/fixtures/seeds/atlas-platform-launch.json +4278 -0
- trueppm_api/apps/projects/fixtures/seeds/aurora-mobile-app.json +2001 -0
- trueppm_api/apps/projects/fixtures/seeds/bayside-civic-center.json +1827 -0
- trueppm_api/apps/projects/fixtures/seeds/ga-launch.json +1909 -0
- trueppm_api/apps/projects/fixtures/seeds/helios-crm-replacement.json +1410 -0
- trueppm_api/apps/projects/guardrail_policy_source.py +269 -0
- trueppm_api/apps/projects/inbound_sync.py +555 -0
- trueppm_api/apps/projects/iteration_label.py +85 -0
- trueppm_api/apps/projects/key_views.py +468 -0
- trueppm_api/apps/projects/keys.py +205 -0
- trueppm_api/apps/projects/lifecycle.py +191 -0
- trueppm_api/apps/projects/management/__init__.py +0 -0
- trueppm_api/apps/projects/management/commands/__init__.py +0 -0
- trueppm_api/apps/projects/management/commands/backfill_in_progress_status.py +92 -0
- trueppm_api/apps/projects/management/commands/create_demo_share_link.py +368 -0
- trueppm_api/apps/projects/management/commands/export_program.py +50 -0
- trueppm_api/apps/projects/management/commands/import_seed.py +165 -0
- trueppm_api/apps/projects/management/commands/load_sample_project.py +514 -0
- trueppm_api/apps/projects/management/commands/seed_capacity.py +406 -0
- trueppm_api/apps/projects/management/commands/seed_integration_fixtures.py +192 -0
- trueppm_api/apps/projects/management/commands/shift_sample_dates.py +120 -0
- trueppm_api/apps/projects/mcp_settings.py +305 -0
- trueppm_api/apps/projects/methodology.py +178 -0
- trueppm_api/apps/projects/migration_helpers.py +75 -0
- trueppm_api/apps/projects/migrations/0001_initial.py +208 -0
- trueppm_api/apps/projects/migrations/0001_squashed_0094_project_decisions_policy.py +5659 -0
- trueppm_api/apps/projects/migrations/0002_alter_uuid_pk_serialize_false.py +57 -0
- trueppm_api/apps/projects/migrations/0003_rename_task_project_index.py +25 -0
- trueppm_api/apps/projects/migrations/0004_soft_delete_and_dependency_versioned.py +70 -0
- trueppm_api/apps/projects/migrations/0005_task_assignee.py +33 -0
- trueppm_api/apps/projects/migrations/0006_task_utilization_index.py +31 -0
- trueppm_api/apps/projects/migrations/0007_task_is_milestone.py +28 -0
- trueppm_api/apps/projects/migrations/0008_baseline.py +119 -0
- trueppm_api/apps/projects/migrations/0009_historicaldependency_historicalproject_and_more.py +210 -0
- trueppm_api/apps/projects/migrations/0010_risk.py +229 -0
- trueppm_api/apps/projects/migrations/0011_task_status.py +27 -0
- trueppm_api/apps/projects/migrations/0012_task_status.py +27 -0
- trueppm_api/apps/projects/migrations/0013_task_planned_start.py +24 -0
- trueppm_api/apps/projects/migrations/0014_short_hex_ids.py +74 -0
- trueppm_api/apps/projects/migrations/0015_backfill_short_ids.py +48 -0
- trueppm_api/apps/projects/migrations/0016_task_actual_dates.py +42 -0
- trueppm_api/apps/projects/migrations/0017_boardcolumnconfig.py +43 -0
- trueppm_api/apps/projects/migrations/0018_estimation_governance.py +62 -0
- trueppm_api/apps/projects/migrations/0019_backfill_wbs_paths.py +28 -0
- trueppm_api/apps/projects/migrations/0020_task_status_5col.py +65 -0
- trueppm_api/apps/projects/migrations/0021_boardsavedview.py +64 -0
- trueppm_api/apps/projects/migrations/0022_task_status_changed_at_priority_rank.py +35 -0
- trueppm_api/apps/projects/migrations/0023_risk_framework_fields.py +96 -0
- trueppm_api/apps/projects/migrations/0024_riskcomment.py +52 -0
- trueppm_api/apps/projects/migrations/0025_sprint.py +352 -0
- trueppm_api/apps/projects/migrations/0026_project_methodology.py +30 -0
- trueppm_api/apps/projects/migrations/0027_sprint_retro.py +89 -0
- trueppm_api/apps/projects/migrations/0028_normalize_notes_field.py +42 -0
- trueppm_api/apps/projects/migrations/0029_complete_implies_full_progress.py +38 -0
- trueppm_api/apps/projects/migrations/0030_review_implies_full_progress.py +37 -0
- trueppm_api/apps/projects/migrations/0031_task_remaining_points.py +22 -0
- trueppm_api/apps/projects/migrations/0032_task_is_subtask_and_sprint_scope_change.py +90 -0
- trueppm_api/apps/projects/migrations/0033_task_my_work_index.py +38 -0
- trueppm_api/apps/projects/migrations/0034_inbound_task_sync.py +313 -0
- trueppm_api/apps/projects/migrations/0035_retro_versioned_and_suggested_assignee.py +173 -0
- trueppm_api/apps/projects/migrations/0036_program_entity_and_membership.py +157 -0
- trueppm_api/apps/projects/migrations/0037_sprint_capacity_points.py +20 -0
- trueppm_api/apps/projects/migrations/0038_taskcomment_commentreaction_commentacknowledgement_and_more.py +233 -0
- trueppm_api/apps/projects/migrations/0039_apitoken_and_more.py +88 -0
- trueppm_api/apps/projects/migrations/0040_program_general_fields.py +119 -0
- trueppm_api/apps/projects/migrations/0041_ceremony_template_and_phase_gate_config.py +210 -0
- trueppm_api/apps/projects/migrations/0041_project_general_fields.py +106 -0
- trueppm_api/apps/projects/migrations/0042_merge_20260522_0410.py +12 -0
- trueppm_api/apps/projects/migrations/0042_program_rollup_config.py +95 -0
- trueppm_api/apps/projects/migrations/0042_workflow_color_and_custom_fields.py +94 -0
- trueppm_api/apps/projects/migrations/0043_merge_20260522_1118.py +10 -0
- trueppm_api/apps/projects/migrations/0044_merge_20260522_rollup.py +10 -0
- trueppm_api/apps/projects/migrations/0044_project_archive_program_close.py +119 -0
- trueppm_api/apps/projects/migrations/0045_program_risk_policy.py +78 -0
- trueppm_api/apps/projects/migrations/0046_merge_20260523_2248.py +12 -0
- trueppm_api/apps/projects/migrations/0047_apitokenauditentry_program_and_more.py +55 -0
- trueppm_api/apps/projects/migrations/0048_historicalprogram_color_program_color.py +32 -0
- trueppm_api/apps/projects/migrations/0049_backlog_item.py +112 -0
- trueppm_api/apps/projects/migrations/0050_backlog_item_trgm_search.py +26 -0
- trueppm_api/apps/projects/migrations/0051_alter_calendar_working_days_alter_dependency_lag_and_more.py +144 -0
- trueppm_api/apps/projects/migrations/0052_recurring_tasks.py +278 -0
- trueppm_api/apps/projects/migrations/0053_dependency_dep_pred_serverver_idx_and_more.py +56 -0
- trueppm_api/apps/projects/migrations/0054_sprintscopechange_goal_impact_and_more.py +117 -0
- trueppm_api/apps/projects/migrations/0055_historicaltask_sprint_pending_and_more.py +51 -0
- trueppm_api/apps/projects/migrations/0056_historicalproject_prioritization_model_and_more.py +276 -0
- trueppm_api/apps/projects/migrations/0057_historicalsprint_binding_committed_snapshot_and_more.py +58 -0
- trueppm_api/apps/projects/migrations/0058_historicaltask_delivery_mode_and_more.py +72 -0
- trueppm_api/apps/projects/migrations/0059_forecastsnapshot.py +80 -0
- trueppm_api/apps/projects/migrations/0060_historicalprojectsignalprivacypolicy_and_more.py +90 -0
- trueppm_api/apps/projects/migrations/0061_baselinetask_story_points.py +17 -0
- trueppm_api/apps/projects/migrations/0062_project_is_sample.py +22 -0
- trueppm_api/apps/projects/migrations/0063_historicalsprint_wip_limit_sprint_wip_limit.py +22 -0
- trueppm_api/apps/projects/migrations/0064_sprinttaskoutcome.py +97 -0
- trueppm_api/apps/projects/migrations/0065_historicalsprint_goal_outcome_sprint_goal_outcome.py +32 -0
- trueppm_api/apps/projects/migrations/0066_historicalproject_lead_project_lead.py +38 -0
- trueppm_api/apps/projects/migrations/0067_sprint_exclude_from_velocity.py +22 -0
- trueppm_api/apps/projects/migrations/0068_project_recalculated_at.py +23 -0
- trueppm_api/apps/projects/migrations/0069_iteration_label.py +22 -0
- trueppm_api/apps/projects/migrations/0070_historicalprogram_iteration_label_and_more.py +32 -0
- trueppm_api/apps/projects/migrations/0071_backfill_iteration_label_inherit.py +35 -0
- trueppm_api/apps/projects/migrations/0072_pulseresponse_retroboarditem.py +129 -0
- trueppm_api/apps/projects/migrations/0073_sprinttaskoutcome_demo_ready.py +17 -0
- trueppm_api/apps/projects/migrations/0074_historicaltask_blocked_reason_task_blocked_reason.py +30 -0
- trueppm_api/apps/projects/migrations/0075_risk_decimal_short_id.py +42 -0
- trueppm_api/apps/projects/migrations/0076_sprinttaskoutcome_review_polish.py +45 -0
- trueppm_api/apps/projects/migrations/0077_task_blocker_fields.py +111 -0
- trueppm_api/apps/projects/migrations/0078_alter_risktask_unique_together_and_more.py +22 -0
- trueppm_api/apps/projects/migrations/0079_historicalproject_status_date_project_status_date.py +22 -0
- trueppm_api/apps/projects/migrations/0080_alter_historicaltask_type_alter_task_type.py +46 -0
- trueppm_api/apps/projects/migrations/0081_historicalprogram_allow_guests_and_more.py +52 -0
- trueppm_api/apps/projects/migrations/0082_project_last_sync_version.py +90 -0
- trueppm_api/apps/projects/migrations/0083_historicalprogram_mc_history_attribution_audience_and_more.py +108 -0
- trueppm_api/apps/projects/migrations/0084_tasknote.py +71 -0
- trueppm_api/apps/projects/migrations/0085_sprint_ix_sprint_velocity.py +33 -0
- trueppm_api/apps/projects/migrations/0086_board_card_search_trgm.py +33 -0
- trueppm_api/apps/projects/migrations/0087_historicalprogram_task_duration_change_percent_policy_and_more.py +155 -0
- trueppm_api/apps/projects/migrations/0088_historicalprogram_allowed_attachment_types_and_more.py +61 -0
- trueppm_api/apps/projects/migrations/0089_signalceilingraiseproposal_signalceilingraisevote_and_more.py +157 -0
- trueppm_api/apps/projects/migrations/0090_historicaltask_proj_histdate_index.py +59 -0
- trueppm_api/apps/projects/migrations/0091_project_board_cadence.py +39 -0
- trueppm_api/apps/projects/migrations/0092_program_target_date.py +22 -0
- trueppm_api/apps/projects/migrations/0093_cross_project_dependency_consent.py +58 -0
- trueppm_api/apps/projects/migrations/0094_project_decisions_policy.py +90 -0
- trueppm_api/apps/projects/migrations/0095_poker_session_vote.py +127 -0
- trueppm_api/apps/projects/migrations/0095_squashed_0097_release_0_3.py +225 -0
- trueppm_api/apps/projects/migrations/0096_crossprojectslipconflict.py +91 -0
- trueppm_api/apps/projects/migrations/0097_backlogitem_backlogitem_tags_gin_and_more.py +32 -0
- trueppm_api/apps/projects/migrations/0098_historicalproject_show_baselines_and_more.py +52 -0
- trueppm_api/apps/projects/migrations/0099_apitoken_scopes.py +48 -0
- trueppm_api/apps/projects/migrations/0100_task_dep_serverver_idx_concurrent.py +75 -0
- trueppm_api/apps/projects/migrations/0101_dependency_deleted_at_task_deleted_at.py +22 -0
- trueppm_api/apps/projects/migrations/0102_project_deleted_at_project_proj_isdel_deletedat_idx.py +25 -0
- trueppm_api/apps/projects/migrations/0103_taskdurationchangeevent_task_dur_evt_sprint_idx.py +18 -0
- trueppm_api/apps/projects/migrations/0104_historicalproject_stale_task_threshold_days_and_more.py +32 -0
- trueppm_api/apps/projects/migrations/0104_trash_restore_1113.py +38 -0
- trueppm_api/apps/projects/migrations/0105_historical_changelog_indexes.py +76 -0
- trueppm_api/apps/projects/migrations/0106_boardsavedview_schema_version.py +20 -0
- trueppm_api/apps/projects/migrations/0106_squashed_0158_release_0_4.py +2357 -0
- trueppm_api/apps/projects/migrations/0107_task_activity_event.py +70 -0
- trueppm_api/apps/projects/migrations/0108_remove_apitoken_api_token_scope_xor_and_more.py +117 -0
- trueppm_api/apps/projects/migrations/0109_projectexportjob.py +82 -0
- trueppm_api/apps/projects/migrations/0110_sharelink.py +123 -0
- trueppm_api/apps/projects/migrations/0111_projectcalendarlayer.py +67 -0
- trueppm_api/apps/projects/migrations/0112_sharelink_expires_at_alter_sharelink_content_kind.py +31 -0
- trueppm_api/apps/projects/migrations/0113_alter_historicaltask_percent_complete_and_more.py +35 -0
- trueppm_api/apps/projects/migrations/0114_historicalproject_default_member_role_and_more.py +28 -0
- trueppm_api/apps/projects/migrations/0115_historicalproject_end_date_shift_threshold_days_and_more.py +22 -0
- trueppm_api/apps/projects/migrations/0116_alter_taskactivityevent_event_type.py +28 -0
- trueppm_api/apps/projects/migrations/0117_label_tasklabel_label_tasks_and_more.py +126 -0
- trueppm_api/apps/projects/migrations/0118_programexportjob.py +82 -0
- trueppm_api/apps/projects/migrations/0119_historicalprogram_calendar_program_calendar.py +36 -0
- trueppm_api/apps/projects/migrations/0120_alter_backlogitem_item_type.py +29 -0
- trueppm_api/apps/projects/migrations/0121_task_three_point_estimate_ordered.py +64 -0
- trueppm_api/apps/projects/migrations/0122_task_relation.py +173 -0
- trueppm_api/apps/projects/migrations/0123_remove_historicalproject_agile_features_and_more.py +20 -0
- trueppm_api/apps/projects/migrations/0124_dependency_is_driving.py +17 -0
- trueppm_api/apps/projects/migrations/0125_historicalprogram_estimation_scale_and_more.py +68 -0
- trueppm_api/apps/projects/migrations/0126_projectcustomfield_show_on_card_taskcustomfieldvalue.py +80 -0
- trueppm_api/apps/projects/migrations/0127_historicalprogram_mcp_enabled_and_more.py +32 -0
- trueppm_api/apps/projects/migrations/0128_acceptancecriterion_sync_seq_apitoken_sync_seq_and_more.py +192 -0
- trueppm_api/apps/projects/migrations/0129_sharelink_show_milestone_dates.py +20 -0
- trueppm_api/apps/projects/migrations/0130_programimportjob.py +85 -0
- trueppm_api/apps/projects/migrations/0131_historicalprogram_sprint_picker_ready_only_default_and_more.py +32 -0
- trueppm_api/apps/projects/migrations/0132_task_scheduled_start.py +17 -0
- trueppm_api/apps/projects/migrations/0133_project_status_date_floor_armed_at.py +17 -0
- trueppm_api/apps/projects/migrations/0134_task_edited_at_task_seeded_at_task_source_id_and_more.py +65 -0
- trueppm_api/apps/projects/migrations/0135_projecttemplate_templateapplication_and_more.py +175 -0
- trueppm_api/apps/projects/migrations/0136_schedule_outline_batch_operations.py +118 -0
- trueppm_api/apps/projects/migrations/0137_collapse_dual_scope_api_tokens.py +54 -0
- trueppm_api/apps/projects/migrations/0138_apitokenauditentry_api_token_audit_owner_idx.py +18 -0
- trueppm_api/apps/projects/migrations/0139_historicaltask_duration_unit_task_duration_unit.py +32 -0
- trueppm_api/apps/projects/migrations/0140_historicaltask_auto_container_and_more.py +113 -0
- trueppm_api/apps/projects/migrations/0141_historicalproject_draft_started_at_and_more.py +44 -0
- trueppm_api/apps/projects/migrations/0142_baseline_calendar_hours_per_day_and_more.py +31 -0
- trueppm_api/apps/projects/migrations/0143_sprintcloserequest_failure_reason_and_more.py +42 -0
- trueppm_api/apps/projects/migrations/0144_projecttemplate_source_project_and_more.py +35 -0
- trueppm_api/apps/projects/migrations/0145_seed_bundled_templates.py +65 -0
- trueppm_api/apps/projects/migrations/0146_historicaltask_board_lane_task_board_lane.py +32 -0
- trueppm_api/apps/projects/migrations/0147_structuraloperation.py +128 -0
- trueppm_api/apps/projects/migrations/0148_task_unique_task_wbs_path_per_project_live.py +76 -0
- trueppm_api/apps/projects/migrations/0149_drop_workshops_tables.py +42 -0
- trueppm_api/apps/projects/migrations/0150_clear_uncommitted_cpm_output.py +130 -0
- trueppm_api/apps/projects/migrations/0151_config_notice_request.py +70 -0
- trueppm_api/apps/projects/migrations/0152_aggregate_task_wbs_name_idx.py +20 -0
- trueppm_api/apps/projects/migrations/0153_program_sample_anchor_date.py +22 -0
- trueppm_api/apps/projects/migrations/0154_object_keys.py +184 -0
- trueppm_api/apps/projects/migrations/0155_task_milestone_at_day_end.py +20 -0
- trueppm_api/apps/projects/migrations/0156_program_import_job_replaced_project_ids.py +17 -0
- trueppm_api/apps/projects/migrations/0157_forecastsnapshot_cpm_finish_at_day_start.py +17 -0
- trueppm_api/apps/projects/migrations/0158_baselinetask_finish_at_day_start.py +17 -0
- trueppm_api/apps/projects/migrations/__init__.py +0 -0
- trueppm_api/apps/projects/models.py +9209 -0
- trueppm_api/apps/projects/poker_services.py +154 -0
- trueppm_api/apps/projects/poker_views.py +398 -0
- trueppm_api/apps/projects/product_backlog_services.py +450 -0
- trueppm_api/apps/projects/program_label_services.py +94 -0
- trueppm_api/apps/projects/program_label_views.py +189 -0
- trueppm_api/apps/projects/program_rollup.py +903 -0
- trueppm_api/apps/projects/program_schedule.py +767 -0
- trueppm_api/apps/projects/program_views.py +3445 -0
- trueppm_api/apps/projects/project_templates.py +422 -0
- trueppm_api/apps/projects/receivers.py +234 -0
- trueppm_api/apps/projects/refusal_codes.py +140 -0
- trueppm_api/apps/projects/reorder_services.py +145 -0
- trueppm_api/apps/projects/restructure_hooks.py +54 -0
- trueppm_api/apps/projects/retro_board_services.py +368 -0
- trueppm_api/apps/projects/retro_services.py +285 -0
- trueppm_api/apps/projects/risk_import.py +396 -0
- trueppm_api/apps/projects/row_identity.py +113 -0
- trueppm_api/apps/projects/schema_migrations.py +228 -0
- trueppm_api/apps/projects/schemas/seed_v1.json +492 -0
- trueppm_api/apps/projects/schemas/seed_v2.json +891 -0
- trueppm_api/apps/projects/seed/__init__.py +61 -0
- trueppm_api/apps/projects/seed/demo_landing_overlay.py +532 -0
- trueppm_api/apps/projects/seed/exporter.py +1717 -0
- trueppm_api/apps/projects/seed/forecast_backfill.py +247 -0
- trueppm_api/apps/projects/seed/importer.py +2764 -0
- trueppm_api/apps/projects/seed/reanchor.py +551 -0
- trueppm_api/apps/projects/seed/reldates.py +126 -0
- trueppm_api/apps/projects/seed/replace.py +128 -0
- trueppm_api/apps/projects/seed/replay.py +1695 -0
- trueppm_api/apps/projects/seed/replay_ctx.py +41 -0
- trueppm_api/apps/projects/seed/samples.py +427 -0
- trueppm_api/apps/projects/seed/validation.py +1169 -0
- trueppm_api/apps/projects/serializers.py +12904 -0
- trueppm_api/apps/projects/services.py +7525 -0
- trueppm_api/apps/projects/share_serializers.py +142 -0
- trueppm_api/apps/projects/share_services.py +373 -0
- trueppm_api/apps/projects/share_views.py +395 -0
- trueppm_api/apps/projects/sharing_settings.py +187 -0
- trueppm_api/apps/projects/signal_privacy_services.py +910 -0
- trueppm_api/apps/projects/signal_privacy_views.py +485 -0
- trueppm_api/apps/projects/signals.py +132 -0
- trueppm_api/apps/projects/slip_conflict.py +288 -0
- trueppm_api/apps/projects/sprint_cadence.py +453 -0
- trueppm_api/apps/projects/sprint_picker_settings.py +132 -0
- trueppm_api/apps/projects/standup.py +304 -0
- trueppm_api/apps/projects/standup_views.py +99 -0
- trueppm_api/apps/projects/structural_operation_services.py +727 -0
- trueppm_api/apps/projects/structural_operation_views.py +311 -0
- trueppm_api/apps/projects/surface_visibility.py +126 -0
- trueppm_api/apps/projects/task_batch_services.py +379 -0
- trueppm_api/apps/projects/task_bulk.py +1244 -0
- trueppm_api/apps/projects/task_classification.py +561 -0
- trueppm_api/apps/projects/task_classification_defaults.py +95 -0
- trueppm_api/apps/projects/task_duration_settings.py +142 -0
- trueppm_api/apps/projects/task_grouping.py +754 -0
- trueppm_api/apps/projects/tasks.py +1979 -0
- trueppm_api/apps/projects/template_divergence.py +168 -0
- trueppm_api/apps/projects/template_services.py +160 -0
- trueppm_api/apps/projects/template_tasks.py +261 -0
- trueppm_api/apps/projects/template_views.py +829 -0
- trueppm_api/apps/projects/throttles.py +311 -0
- trueppm_api/apps/projects/urls.py +1016 -0
- trueppm_api/apps/projects/utilization.py +909 -0
- trueppm_api/apps/projects/views.py +21225 -0
- trueppm_api/apps/projects/wbs_paths.py +119 -0
- trueppm_api/apps/resources/__init__.py +0 -0
- trueppm_api/apps/resources/apps.py +8 -0
- trueppm_api/apps/resources/capacity.py +121 -0
- trueppm_api/apps/resources/migrations/0001_initial.py +68 -0
- trueppm_api/apps/resources/migrations/0001_squashed_0013_alter_projectresource_unique_together_and_more.py +281 -0
- trueppm_api/apps/resources/migrations/0002_alter_uuid_pk_serialize_false.py +36 -0
- trueppm_api/apps/resources/migrations/0003_resource_soft_delete.py +30 -0
- trueppm_api/apps/resources/migrations/0004_add_taskresource_resource_index.py +25 -0
- trueppm_api/apps/resources/migrations/0005_resource_job_role.py +20 -0
- trueppm_api/apps/resources/migrations/0006_skill.py +34 -0
- trueppm_api/apps/resources/migrations/0007_resource_skill.py +63 -0
- trueppm_api/apps/resources/migrations/0008_project_resource.py +63 -0
- trueppm_api/apps/resources/migrations/0009_task_skill_requirement.py +60 -0
- trueppm_api/apps/resources/migrations/0010_alter_resourceskill_options_and_more.py +20 -0
- trueppm_api/apps/resources/migrations/0011_alter_projectresource_notes.py +17 -0
- trueppm_api/apps/resources/migrations/0012_add_resource_user_fk.py +26 -0
- trueppm_api/apps/resources/migrations/0013_alter_projectresource_unique_together_and_more.py +53 -0
- trueppm_api/apps/resources/migrations/0014_projectresource_sync_seq_resource_sync_seq_and_more.py +37 -0
- trueppm_api/apps/resources/migrations/0014_squashed_0015_release_0_4.py +47 -0
- trueppm_api/apps/resources/migrations/0015_projectresource_deactivated_with_resource.py +17 -0
- trueppm_api/apps/resources/migrations/__init__.py +0 -0
- trueppm_api/apps/resources/models.py +298 -0
- trueppm_api/apps/resources/serializers.py +426 -0
- trueppm_api/apps/resources/services.py +465 -0
- trueppm_api/apps/resources/urls.py +28 -0
- trueppm_api/apps/resources/views.py +1752 -0
- trueppm_api/apps/scheduling/__init__.py +0 -0
- trueppm_api/apps/scheduling/apps.py +153 -0
- trueppm_api/apps/scheduling/calendars.py +144 -0
- trueppm_api/apps/scheduling/deadletter.py +91 -0
- trueppm_api/apps/scheduling/finish_reading.py +198 -0
- trueppm_api/apps/scheduling/forecast_history_settings.py +215 -0
- trueppm_api/apps/scheduling/forecast_staleness.py +313 -0
- trueppm_api/apps/scheduling/graph_guard.py +263 -0
- trueppm_api/apps/scheduling/management/__init__.py +0 -0
- trueppm_api/apps/scheduling/management/commands/__init__.py +0 -0
- trueppm_api/apps/scheduling/management/commands/prune_forecast_snapshots.py +53 -0
- trueppm_api/apps/scheduling/mc_admission.py +181 -0
- trueppm_api/apps/scheduling/migrations/0001_failed_task.py +62 -0
- trueppm_api/apps/scheduling/migrations/0001_squashed_0007_projectforecastsnapshot.py +309 -0
- trueppm_api/apps/scheduling/migrations/0002_schedulerequest.py +78 -0
- trueppm_api/apps/scheduling/migrations/0003_add_schedule_request_reason.py +27 -0
- trueppm_api/apps/scheduling/migrations/0004_velocity_suggestion.py +94 -0
- trueppm_api/apps/scheduling/migrations/0005_montecarlorun.py +61 -0
- trueppm_api/apps/scheduling/migrations/0006_montecarlorun_distribution.py +17 -0
- trueppm_api/apps/scheduling/migrations/0007_projectforecastsnapshot.py +65 -0
- trueppm_api/apps/scheduling/migrations/0008_alter_schedulerequest_reason.py +28 -0
- trueppm_api/apps/scheduling/migrations/0008_folded_schedulerequest_reason.py +34 -0
- trueppm_api/apps/scheduling/migrations/0009_alter_schedulerequest_reason.py +29 -0
- trueppm_api/apps/scheduling/migrations/0010_failedtask_resolution_note_failedtask_resolved_at_and_more.py +43 -0
- trueppm_api/apps/scheduling/migrations/0010_squashed_0016_release_0_4.py +106 -0
- trueppm_api/apps/scheduling/migrations/0011_failedtask_project.py +26 -0
- trueppm_api/apps/scheduling/migrations/0012_montecarlorun_diagnostic.py +17 -0
- trueppm_api/apps/scheduling/migrations/0013_montecarlorun_status_date.py +17 -0
- trueppm_api/apps/scheduling/migrations/0014_montecarlorun_plan_version.py +17 -0
- trueppm_api/apps/scheduling/migrations/0015_projectforecastsnapshot_cpm_finish_at_day_start.py +17 -0
- trueppm_api/apps/scheduling/migrations/0016_montecarlorun_finish_readings.py +32 -0
- trueppm_api/apps/scheduling/migrations/__init__.py +0 -0
- trueppm_api/apps/scheduling/models.py +542 -0
- trueppm_api/apps/scheduling/receivers.py +160 -0
- trueppm_api/apps/scheduling/risk_premium.py +334 -0
- trueppm_api/apps/scheduling/serializers.py +723 -0
- trueppm_api/apps/scheduling/services.py +1251 -0
- trueppm_api/apps/scheduling/signals.py +56 -0
- trueppm_api/apps/scheduling/tasks.py +2248 -0
- trueppm_api/apps/scheduling/telemetry.py +80 -0
- trueppm_api/apps/scheduling/units.py +35 -0
- trueppm_api/apps/scheduling/urls.py +57 -0
- trueppm_api/apps/scheduling/views.py +2908 -0
- trueppm_api/apps/sso/__init__.py +0 -0
- trueppm_api/apps/sso/apps.py +19 -0
- trueppm_api/apps/sso/extensions.py +130 -0
- trueppm_api/apps/sso/management/__init__.py +0 -0
- trueppm_api/apps/sso/management/commands/__init__.py +0 -0
- trueppm_api/apps/sso/management/commands/seed_sso_keycloak.py +172 -0
- trueppm_api/apps/sso/migrations/0001_initial.py +119 -0
- trueppm_api/apps/sso/migrations/0002_remove_oidcprovider_workspace_ssoproviderpolicy_and_more.py +169 -0
- trueppm_api/apps/sso/migrations/__init__.py +0 -0
- trueppm_api/apps/sso/models.py +148 -0
- trueppm_api/apps/sso/serializers.py +446 -0
- trueppm_api/apps/sso/services.py +1473 -0
- trueppm_api/apps/sso/urls.py +47 -0
- trueppm_api/apps/sso/views.py +935 -0
- trueppm_api/apps/sync/__init__.py +0 -0
- trueppm_api/apps/sync/apps.py +15 -0
- trueppm_api/apps/sync/backfill.py +208 -0
- trueppm_api/apps/sync/broadcast.py +369 -0
- trueppm_api/apps/sync/conflict.py +262 -0
- trueppm_api/apps/sync/consumers.py +548 -0
- trueppm_api/apps/sync/migrations/0001_initial.py +59 -0
- trueppm_api/apps/sync/migrations/0001_squashed_0002_remove_syncbatch_syncbatch_project_client_batch_uniq_and_more.py +77 -0
- trueppm_api/apps/sync/migrations/0002_remove_syncbatch_syncbatch_project_client_batch_uniq_and_more.py +41 -0
- trueppm_api/apps/sync/migrations/0003_boardevent.py +46 -0
- trueppm_api/apps/sync/migrations/0003_squashed_0005_release_0_4.py +77 -0
- trueppm_api/apps/sync/migrations/0004_seed_sync_seq.py +24 -0
- trueppm_api/apps/sync/migrations/0005_program_sync_sequence.py +35 -0
- trueppm_api/apps/sync/migrations/0006_boardevent_per_project_seq.py +77 -0
- trueppm_api/apps/sync/migrations/__init__.py +0 -0
- trueppm_api/apps/sync/models.py +272 -0
- trueppm_api/apps/sync/pagination.py +231 -0
- trueppm_api/apps/sync/sequence.py +488 -0
- trueppm_api/apps/sync/serializers.py +688 -0
- trueppm_api/apps/sync/tasks.py +260 -0
- trueppm_api/apps/sync/throttles.py +175 -0
- trueppm_api/apps/sync/upload.py +556 -0
- trueppm_api/apps/sync/urls.py +17 -0
- trueppm_api/apps/sync/views.py +957 -0
- trueppm_api/apps/sync/ws_auth.py +193 -0
- trueppm_api/apps/taskruns/__init__.py +0 -0
- trueppm_api/apps/taskruns/apps.py +11 -0
- trueppm_api/apps/taskruns/migrations/0001_initial.py +92 -0
- trueppm_api/apps/taskruns/migrations/__init__.py +0 -0
- trueppm_api/apps/taskruns/models.py +68 -0
- trueppm_api/apps/taskruns/serializers.py +92 -0
- trueppm_api/apps/taskruns/tasks.py +60 -0
- trueppm_api/apps/taskruns/tracker.py +286 -0
- trueppm_api/apps/taskruns/urls.py +46 -0
- trueppm_api/apps/taskruns/views.py +195 -0
- trueppm_api/apps/teams/__init__.py +8 -0
- trueppm_api/apps/teams/apps.py +16 -0
- trueppm_api/apps/teams/migrations/0001_initial.py +139 -0
- trueppm_api/apps/teams/migrations/0001_squashed_0002_default_teams.py +159 -0
- trueppm_api/apps/teams/migrations/0002_default_teams.py +62 -0
- trueppm_api/apps/teams/migrations/0003_team_sync_seq_teammembership_sync_seq.py +22 -0
- trueppm_api/apps/teams/migrations/0004_backfill_default_teams_on_upgrade.py +49 -0
- trueppm_api/apps/teams/migrations/__init__.py +0 -0
- trueppm_api/apps/teams/models.py +145 -0
- trueppm_api/apps/teams/permissions.py +149 -0
- trueppm_api/apps/teams/serializers.py +95 -0
- trueppm_api/apps/teams/services.py +440 -0
- trueppm_api/apps/teams/signals.py +61 -0
- trueppm_api/apps/teams/urls.py +34 -0
- trueppm_api/apps/teams/views.py +201 -0
- trueppm_api/apps/timetracking/__init__.py +0 -0
- trueppm_api/apps/timetracking/apps.py +9 -0
- trueppm_api/apps/timetracking/migrations/0001_initial.py +117 -0
- trueppm_api/apps/timetracking/migrations/0001_squashed_0004_release_0_4.py +167 -0
- trueppm_api/apps/timetracking/migrations/0002_timesheetsubmission.py +46 -0
- trueppm_api/apps/timetracking/migrations/0003_timeentry_deleted_at_timeentry_deleted_by.py +31 -0
- trueppm_api/apps/timetracking/migrations/0004_timeentry_sync_seq_and_more.py +24 -0
- trueppm_api/apps/timetracking/migrations/__init__.py +0 -0
- trueppm_api/apps/timetracking/models.py +178 -0
- trueppm_api/apps/timetracking/serializers.py +175 -0
- trueppm_api/apps/timetracking/services.py +211 -0
- trueppm_api/apps/timetracking/urls.py +47 -0
- trueppm_api/apps/timetracking/views.py +597 -0
- trueppm_api/apps/webhooks/__init__.py +0 -0
- trueppm_api/apps/webhooks/apps.py +8 -0
- trueppm_api/apps/webhooks/backfill.py +90 -0
- trueppm_api/apps/webhooks/dispatch.py +279 -0
- trueppm_api/apps/webhooks/migrations/0001_initial.py +146 -0
- trueppm_api/apps/webhooks/migrations/0001_squashed_0007_sprint_lifecycle_events.py +249 -0
- trueppm_api/apps/webhooks/migrations/0002_alter_webhook_events.py +32 -0
- trueppm_api/apps/webhooks/migrations/0003_delivery_status_created_idx.py +17 -0
- trueppm_api/apps/webhooks/migrations/0004_webhook_program_alter_webhook_project_and_more.py +64 -0
- trueppm_api/apps/webhooks/migrations/0005_webhook_delivery_sequence_numbers.py +30 -0
- trueppm_api/apps/webhooks/migrations/0006_webhook_format_alter_webhook_events_and_more.py +61 -0
- trueppm_api/apps/webhooks/migrations/0007_sprint_lifecycle_events.py +63 -0
- trueppm_api/apps/webhooks/migrations/0008_risk_baseline_comment_events.py +73 -0
- trueppm_api/apps/webhooks/migrations/0009_encrypt_webhook_secret_and_failure_counters.py +100 -0
- trueppm_api/apps/webhooks/migrations/0010_alter_webhook_disabled_at.py +21 -0
- trueppm_api/apps/webhooks/migrations/0011_webhookeditor.py +48 -0
- trueppm_api/apps/webhooks/migrations/0012_alter_webhook_disabled_at.py +21 -0
- trueppm_api/apps/webhooks/migrations/__init__.py +0 -0
- trueppm_api/apps/webhooks/models.py +437 -0
- trueppm_api/apps/webhooks/serializers.py +326 -0
- trueppm_api/apps/webhooks/tasks.py +680 -0
- trueppm_api/apps/webhooks/urls.py +22 -0
- trueppm_api/apps/webhooks/views.py +533 -0
- trueppm_api/apps/workflow_engine/__init__.py +0 -0
- trueppm_api/apps/workflow_engine/apps.py +23 -0
- trueppm_api/apps/workflow_engine/migrations/0001_initial.py +230 -0
- trueppm_api/apps/workflow_engine/migrations/0001_squashed_0002_remove_workflowhistoryevent_workflow_history_lookup_idx.py +234 -0
- trueppm_api/apps/workflow_engine/migrations/0002_remove_workflowhistoryevent_workflow_history_lookup_idx.py +16 -0
- trueppm_api/apps/workflow_engine/migrations/0003_workflowoutboxrow_workflow_outbox_recovery_idx.py +21 -0
- trueppm_api/apps/workflow_engine/migrations/__init__.py +0 -0
- trueppm_api/apps/workflow_engine/models.py +265 -0
- trueppm_api/apps/workflow_engine/tasks.py +371 -0
- trueppm_api/apps/workspace/__init__.py +0 -0
- trueppm_api/apps/workspace/apps.py +10 -0
- trueppm_api/apps/workspace/backfill.py +111 -0
- trueppm_api/apps/workspace/export.py +254 -0
- trueppm_api/apps/workspace/migrations/0001_initial.py +326 -0
- trueppm_api/apps/workspace/migrations/0001_squashed_0014_workspacemembership_availability_effective_from_and_more.py +829 -0
- trueppm_api/apps/workspace/migrations/0002_remove_workspace_fiscal_year_start_and_more.py +85 -0
- trueppm_api/apps/workspace/migrations/0003_workspaceexportjob.py +73 -0
- trueppm_api/apps/workspace/migrations/0004_alter_workspaceinvite_status.py +27 -0
- trueppm_api/apps/workspace/migrations/0005_workspace_iteration_label_and_more.py +26 -0
- trueppm_api/apps/workspace/migrations/0006_alter_groupmembership_unique_together_and_more.py +45 -0
- trueppm_api/apps/workspace/migrations/0007_workspace_public_sharing_override_policy.py +21 -0
- trueppm_api/apps/workspace/migrations/0008_workspace_mc_history_attribution_audience_and_more.py +44 -0
- trueppm_api/apps/workspace/migrations/0009_workspace_methodology_and_more.py +186 -0
- trueppm_api/apps/workspace/migrations/0010_workspace_logo.py +38 -0
- trueppm_api/apps/workspace/migrations/0011_historicalworkspace_task_duration_change_percent_override_policy_and_more.py +56 -0
- trueppm_api/apps/workspace/migrations/0012_historicalworkspace_allowed_attachment_types_and_more.py +64 -0
- trueppm_api/apps/workspace/migrations/0013_auditevent.py +70 -0
- trueppm_api/apps/workspace/migrations/0014_workspacemembership_availability_effective_from_and_more.py +39 -0
- trueppm_api/apps/workspace/migrations/0015_squashed_0027_release_0_4.py +199 -0
- trueppm_api/apps/workspace/migrations/0015_trash_restore_1113.py +34 -0
- trueppm_api/apps/workspace/migrations/0016_historicalworkspace_calendar_and_more.py +55 -0
- trueppm_api/apps/workspace/migrations/0017_historicalworkspace_estimation_scale_and_more.py +38 -0
- trueppm_api/apps/workspace/migrations/0018_historicalworkspace_feedback_enabled_and_more.py +32 -0
- trueppm_api/apps/workspace/migrations/0019_historicalworkspace_mcp_enabled_and_more.py +22 -0
- trueppm_api/apps/workspace/migrations/0020_viewer_ordinal_one.py +34 -0
- trueppm_api/apps/workspace/migrations/0021_group_sync_seq_groupmembership_sync_seq_and_more.py +27 -0
- trueppm_api/apps/workspace/migrations/0022_historicalworkspace_sprint_picker_ready_only_default_and_more.py +22 -0
- trueppm_api/apps/workspace/migrations/0023_alter_auditevent_event_type.py +32 -0
- trueppm_api/apps/workspace/migrations/0024_alter_auditevent_event_type.py +33 -0
- trueppm_api/apps/workspace/migrations/0025_alter_auditevent_event_type.py +36 -0
- trueppm_api/apps/workspace/migrations/0026_alter_auditevent_event_type.py +37 -0
- trueppm_api/apps/workspace/migrations/0027_alter_auditevent_event_type.py +42 -0
- trueppm_api/apps/workspace/migrations/__init__.py +0 -0
- trueppm_api/apps/workspace/models.py +857 -0
- trueppm_api/apps/workspace/permissions.py +187 -0
- trueppm_api/apps/workspace/serializers.py +590 -0
- trueppm_api/apps/workspace/services.py +967 -0
- trueppm_api/apps/workspace/signals.py +37 -0
- trueppm_api/apps/workspace/tasks.py +616 -0
- trueppm_api/apps/workspace/urls.py +113 -0
- trueppm_api/apps/workspace/views.py +1581 -0
- trueppm_api/asgi.py +49 -0
- trueppm_api/celery.py +40 -0
- trueppm_api/core/__init__.py +0 -0
- trueppm_api/core/admin_site.py +206 -0
- trueppm_api/core/auth_views.py +934 -0
- trueppm_api/core/constant_time.py +51 -0
- trueppm_api/core/csp.py +54 -0
- trueppm_api/core/db.py +87 -0
- trueppm_api/core/db_session.py +37 -0
- trueppm_api/core/demo_read_only.py +314 -0
- trueppm_api/core/exception_handlers.py +157 -0
- trueppm_api/core/export_downloads.py +56 -0
- trueppm_api/core/extension_providers.py +56 -0
- trueppm_api/core/extension_signals.py +147 -0
- trueppm_api/core/idempotent.py +260 -0
- trueppm_api/core/metadata.py +42 -0
- trueppm_api/core/middleware.py +51 -0
- trueppm_api/core/openapi.py +1221 -0
- trueppm_api/core/password_reset.py +513 -0
- trueppm_api/core/protect_conflict.py +100 -0
- trueppm_api/core/ratelimit.py +148 -0
- trueppm_api/core/redis_throttle.py +82 -0
- trueppm_api/core/refresh_cookie_policy.py +156 -0
- trueppm_api/core/request_body.py +86 -0
- trueppm_api/core/security_checks.py +1034 -0
- trueppm_api/core/storage_config.py +105 -0
- trueppm_api/core/text_decode.py +168 -0
- trueppm_api/core/throttling.py +514 -0
- trueppm_api/core/valkey.py +214 -0
- trueppm_api/core/valkey_cache.py +66 -0
- trueppm_api/core/valkey_checks.py +104 -0
- trueppm_api/core/valkey_config.py +39 -0
- trueppm_api/core/worker_broker_wait.py +149 -0
- trueppm_api/core/worker_heartbeat.py +134 -0
- trueppm_api/core/worker_selfheal.py +205 -0
- trueppm_api/fields.py +36 -0
- trueppm_api/permissions.py +30 -0
- trueppm_api/py.typed +0 -0
- trueppm_api/routing.py +11 -0
- trueppm_api/settings/__init__.py +0 -0
- trueppm_api/settings/base.py +2605 -0
- trueppm_api/settings/dev.py +296 -0
- trueppm_api/settings/prod.py +265 -0
- trueppm_api/urls.py +217 -0
- trueppm_api/workflows/__init__.py +38 -0
- trueppm_api/workflows/backends/__init__.py +6 -0
- trueppm_api/workflows/backends/default.py +297 -0
- trueppm_api/workflows/consumers/__init__.py +11 -0
- trueppm_api/workflows/consumers/requeue_failed_task.py +65 -0
- trueppm_api/workflows/interface.py +148 -0
- trueppm_api/workflows/registry.py +106 -0
- trueppm_api/workflows/services.py +90 -0
- trueppm_api/wsgi.py +11 -0
- trueppm_api-0.4.0.dist-info/METADATA +273 -0
- trueppm_api-0.4.0.dist-info/RECORD +799 -0
- trueppm_api-0.4.0.dist-info/WHEEL +4 -0
- trueppm_api-0.4.0.dist-info/licenses/LICENSE +201 -0
- trueppm_api-0.4.0.dist-info/licenses/NOTICE +7 -0
- trueppm_api-0.4.0.dist-info/licenses/NOTICES +104 -0
- trueppm_api-0.4.0.dist-info/licenses/licenses/GPL-3.0.txt +674 -0
- trueppm_api-0.4.0.dist-info/licenses/licenses/LGPL-3.0.txt +165 -0
- trueppm_api-0.4.0.dist-info/licenses/licenses/MPL-2.0.txt +373 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Generated by Django 5.2.14 on 2026-05-30 22:19
|
|
2
|
+
|
|
3
|
+
import django.db.models.deletion
|
|
4
|
+
from django.conf import settings
|
|
5
|
+
from django.db import migrations, models
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Migration(migrations.Migration):
|
|
9
|
+
dependencies = [
|
|
10
|
+
("projects", "0054_sprintscopechange_goal_impact_and_more"),
|
|
11
|
+
("sync", "0001_initial"),
|
|
12
|
+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
operations = [
|
|
16
|
+
migrations.RemoveConstraint(
|
|
17
|
+
model_name="syncbatch",
|
|
18
|
+
name="syncbatch_project_client_batch_uniq",
|
|
19
|
+
),
|
|
20
|
+
migrations.AddField(
|
|
21
|
+
model_name="syncbatch",
|
|
22
|
+
name="actor_user",
|
|
23
|
+
field=models.ForeignKey(
|
|
24
|
+
blank=True,
|
|
25
|
+
null=True,
|
|
26
|
+
on_delete=django.db.models.deletion.CASCADE,
|
|
27
|
+
related_name="sync_batches",
|
|
28
|
+
to=settings.AUTH_USER_MODEL,
|
|
29
|
+
),
|
|
30
|
+
),
|
|
31
|
+
# safe-constraint: widens the (project, client_batch_id) uniqueness removed
|
|
32
|
+
# above to (project, actor_user, client_batch_id). A superset of an already
|
|
33
|
+
# unique key is unique, so no existing row can violate the wider constraint.
|
|
34
|
+
migrations.AddConstraint(
|
|
35
|
+
model_name="syncbatch",
|
|
36
|
+
constraint=models.UniqueConstraint(
|
|
37
|
+
fields=("project", "actor_user", "client_batch_id"),
|
|
38
|
+
name="syncbatch_project_actor_client_batch_uniq",
|
|
39
|
+
),
|
|
40
|
+
),
|
|
41
|
+
]
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Generated by Django 5.2.15 on 2026-07-05 23:56
|
|
2
|
+
|
|
3
|
+
import django.db.models.deletion
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
dependencies = [
|
|
9
|
+
("projects", "0109_projectexportjob"),
|
|
10
|
+
(
|
|
11
|
+
"sync",
|
|
12
|
+
"0001_squashed_0002_remove_syncbatch_syncbatch_project_client_batch_uniq_and_more",
|
|
13
|
+
),
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
operations = [
|
|
17
|
+
migrations.CreateModel(
|
|
18
|
+
name="BoardEvent",
|
|
19
|
+
fields=[
|
|
20
|
+
(
|
|
21
|
+
"id",
|
|
22
|
+
models.BigAutoField(
|
|
23
|
+
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
|
24
|
+
),
|
|
25
|
+
),
|
|
26
|
+
("event_type", models.CharField(max_length=64)),
|
|
27
|
+
("payload", models.JSONField(blank=True, default=dict)),
|
|
28
|
+
("created_at", models.DateTimeField(auto_now_add=True)),
|
|
29
|
+
(
|
|
30
|
+
"project",
|
|
31
|
+
models.ForeignKey(
|
|
32
|
+
on_delete=django.db.models.deletion.CASCADE,
|
|
33
|
+
related_name="board_events",
|
|
34
|
+
to="projects.project",
|
|
35
|
+
),
|
|
36
|
+
),
|
|
37
|
+
],
|
|
38
|
+
options={
|
|
39
|
+
"ordering": ["id"],
|
|
40
|
+
"indexes": [
|
|
41
|
+
models.Index(fields=["project", "id"], name="boardevent_project_seq_idx"),
|
|
42
|
+
models.Index(fields=["created_at"], name="boardevent_created_idx"),
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
),
|
|
46
|
+
]
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Generated by Django 5.2.17 on 2026-10-05 20:38
|
|
2
|
+
|
|
3
|
+
import django.db.models.deletion
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
|
|
6
|
+
import trueppm_api.apps.sync.backfill
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Migration(migrations.Migration):
|
|
10
|
+
replaces = [
|
|
11
|
+
("sync", "0003_boardevent"),
|
|
12
|
+
("sync", "0004_seed_sync_seq"),
|
|
13
|
+
("sync", "0005_program_sync_sequence"),
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
dependencies = [
|
|
17
|
+
("access", "0018_programmembership_sync_seq_and_more"),
|
|
18
|
+
("integrations", "0011_tasklink_sync_seq_tasklink_tasklink_syncseq_idx"),
|
|
19
|
+
("projects", "0109_projectexportjob"),
|
|
20
|
+
("projects", "0128_acceptancecriterion_sync_seq_apitoken_sync_seq_and_more"),
|
|
21
|
+
(
|
|
22
|
+
"sync",
|
|
23
|
+
"0001_squashed_0002_remove_syncbatch_syncbatch_project_client_batch_uniq_and_more",
|
|
24
|
+
),
|
|
25
|
+
("timetracking", "0004_timeentry_sync_seq_and_more"),
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
operations = [
|
|
29
|
+
migrations.CreateModel(
|
|
30
|
+
name="BoardEvent",
|
|
31
|
+
fields=[
|
|
32
|
+
(
|
|
33
|
+
"id",
|
|
34
|
+
models.BigAutoField(
|
|
35
|
+
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
|
36
|
+
),
|
|
37
|
+
),
|
|
38
|
+
("event_type", models.CharField(max_length=64)),
|
|
39
|
+
("payload", models.JSONField(blank=True, default=dict)),
|
|
40
|
+
("created_at", models.DateTimeField(auto_now_add=True)),
|
|
41
|
+
(
|
|
42
|
+
"project",
|
|
43
|
+
models.ForeignKey(
|
|
44
|
+
on_delete=django.db.models.deletion.CASCADE,
|
|
45
|
+
related_name="board_events",
|
|
46
|
+
to="projects.project",
|
|
47
|
+
),
|
|
48
|
+
),
|
|
49
|
+
],
|
|
50
|
+
options={
|
|
51
|
+
"ordering": ["id"],
|
|
52
|
+
"indexes": [
|
|
53
|
+
models.Index(fields=["project", "id"], name="boardevent_project_seq_idx"),
|
|
54
|
+
models.Index(fields=["created_at"], name="boardevent_created_idx"),
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
),
|
|
58
|
+
migrations.RunPython(
|
|
59
|
+
code=trueppm_api.apps.sync.backfill.seed_sync_seq,
|
|
60
|
+
reverse_code=trueppm_api.apps.sync.backfill.unseed_sync_seq,
|
|
61
|
+
),
|
|
62
|
+
migrations.CreateModel(
|
|
63
|
+
name="ProgramSyncSequence",
|
|
64
|
+
fields=[
|
|
65
|
+
("id", models.BigAutoField(primary_key=True, serialize=False)),
|
|
66
|
+
("value", models.BigIntegerField(default=0, editable=False)),
|
|
67
|
+
],
|
|
68
|
+
options={
|
|
69
|
+
"verbose_name": "program sync sequence",
|
|
70
|
+
"verbose_name_plural": "program sync sequence",
|
|
71
|
+
},
|
|
72
|
+
),
|
|
73
|
+
migrations.RunPython(
|
|
74
|
+
code=trueppm_api.apps.sync.backfill.seed_program_sync_seq,
|
|
75
|
+
reverse_code=trueppm_api.apps.sync.backfill.unseed_program_sync_seq,
|
|
76
|
+
),
|
|
77
|
+
]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""Seed the per-project sync delta cursor for existing data (ADR-0686, #2491).
|
|
2
|
+
|
|
3
|
+
Runs after every app that adds the ``sync_seq`` column, because the renumber
|
|
4
|
+
touches all of them in one pass. The logic lives in ``apps/sync/backfill.py`` so
|
|
5
|
+
tests can import it without referencing this file's name (CLAUDE.md rule 3).
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from django.db import migrations
|
|
9
|
+
|
|
10
|
+
from trueppm_api.apps.sync.backfill import seed_sync_seq, unseed_sync_seq
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Migration(migrations.Migration):
|
|
14
|
+
dependencies = [
|
|
15
|
+
("sync", "0003_boardevent"),
|
|
16
|
+
("projects", "0128_acceptancecriterion_sync_seq_apitoken_sync_seq_and_more"),
|
|
17
|
+
("access", "0018_programmembership_sync_seq_and_more"),
|
|
18
|
+
("integrations", "0011_tasklink_sync_seq_tasklink_tasklink_syncseq_idx"),
|
|
19
|
+
("timetracking", "0004_timeentry_sync_seq_and_more"),
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
operations = [
|
|
23
|
+
migrations.RunPython(seed_sync_seq, unseed_sync_seq, elidable=True),
|
|
24
|
+
]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Installation-wide allocator for the program sync cursor (ADR-0747, #2498).
|
|
2
|
+
|
|
3
|
+
Creates the singleton counter, then seeds it and both program tables' ``sync_seq``
|
|
4
|
+
in one ordered pass. The backfill logic lives in ``apps/sync/backfill.py`` so tests
|
|
5
|
+
can import it without referencing this file's name (CLAUDE.md migration rule 3).
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from django.db import migrations, models
|
|
9
|
+
|
|
10
|
+
from trueppm_api.apps.sync.backfill import seed_program_sync_seq, unseed_program_sync_seq
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Migration(migrations.Migration):
|
|
14
|
+
dependencies = [
|
|
15
|
+
("sync", "0004_seed_sync_seq"),
|
|
16
|
+
# The backfill reads both tables' server_version and writes their sync_seq,
|
|
17
|
+
# so both columns must already exist.
|
|
18
|
+
("projects", "0128_acceptancecriterion_sync_seq_apitoken_sync_seq_and_more"),
|
|
19
|
+
("access", "0018_programmembership_sync_seq_and_more"),
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
operations = [
|
|
23
|
+
migrations.CreateModel(
|
|
24
|
+
name="ProgramSyncSequence",
|
|
25
|
+
fields=[
|
|
26
|
+
("id", models.BigAutoField(primary_key=True, serialize=False)),
|
|
27
|
+
("value", models.BigIntegerField(default=0, editable=False)),
|
|
28
|
+
],
|
|
29
|
+
options={
|
|
30
|
+
"verbose_name": "program sync sequence",
|
|
31
|
+
"verbose_name_plural": "program sync sequence",
|
|
32
|
+
},
|
|
33
|
+
),
|
|
34
|
+
migrations.RunPython(seed_program_sync_seq, unseed_program_sync_seq, elidable=True),
|
|
35
|
+
]
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Generated by Django 5.2.17 on 2026-10-14 15:35
|
|
2
|
+
|
|
3
|
+
"""Per-project, commit-ordered WebSocket replay sequence (ADR-1285, #4386).
|
|
4
|
+
|
|
5
|
+
Adds ``BoardEvent.seq`` and the per-project ``BoardEventSequence`` allocator. It
|
|
6
|
+
seeds each project's counter at that project's highest existing global id plus
|
|
7
|
+
``BOARD_EVENT_SEQ_UPGRADE_OFFSET`` (2**32), so every new per-project ``seq`` sits far
|
|
8
|
+
above any global id, including ids old pods issue during the rolling update. Every
|
|
9
|
+
pre-upgrade cursor therefore gets one ``resync_required``. See
|
|
10
|
+
``seed_board_event_sequences``.
|
|
11
|
+
|
|
12
|
+
Existing rows are not renumbered: they keep ``seq = NULL`` and stay live-only. The
|
|
13
|
+
same holds for rows a pod still running the previous release INSERTs during a
|
|
14
|
+
rolling update (it does not know the column). The window is disclosed in the
|
|
15
|
+
upgrade notes.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from typing import Any
|
|
19
|
+
|
|
20
|
+
import django.db.models.deletion
|
|
21
|
+
from django.db import migrations, models
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _seed(apps: Any, schema_editor: Any) -> None:
|
|
25
|
+
from trueppm_api.apps.sync.sequence import seed_board_event_sequences
|
|
26
|
+
|
|
27
|
+
seed_board_event_sequences(
|
|
28
|
+
apps.get_model("sync", "BoardEvent"),
|
|
29
|
+
apps.get_model("sync", "BoardEventSequence"),
|
|
30
|
+
apps.get_model("projects", "Project"),
|
|
31
|
+
schema_editor.connection,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class Migration(migrations.Migration):
|
|
36
|
+
dependencies = [
|
|
37
|
+
("projects", "0106_squashed_0158_release_0_4"),
|
|
38
|
+
("sync", "0003_squashed_0005_release_0_4"),
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
operations = [
|
|
42
|
+
migrations.CreateModel(
|
|
43
|
+
name="BoardEventSequence",
|
|
44
|
+
fields=[
|
|
45
|
+
(
|
|
46
|
+
"project",
|
|
47
|
+
models.OneToOneField(
|
|
48
|
+
on_delete=django.db.models.deletion.CASCADE,
|
|
49
|
+
primary_key=True,
|
|
50
|
+
related_name="board_event_sequence",
|
|
51
|
+
serialize=False,
|
|
52
|
+
to="projects.project",
|
|
53
|
+
),
|
|
54
|
+
),
|
|
55
|
+
("value", models.BigIntegerField(default=0, editable=False)),
|
|
56
|
+
],
|
|
57
|
+
),
|
|
58
|
+
migrations.AddField(
|
|
59
|
+
model_name="boardevent",
|
|
60
|
+
name="seq",
|
|
61
|
+
field=models.BigIntegerField(blank=True, editable=False, null=True),
|
|
62
|
+
),
|
|
63
|
+
# Reverse is a no-op: unapplying CreateModel drops the counter table.
|
|
64
|
+
migrations.RunPython(_seed, migrations.RunPython.noop),
|
|
65
|
+
migrations.RemoveIndex(
|
|
66
|
+
model_name="boardevent",
|
|
67
|
+
name="boardevent_project_seq_idx",
|
|
68
|
+
),
|
|
69
|
+
# safe-constraint: seq was added by this migration and nothing writes it, so
|
|
70
|
+
# every existing row is NULL, and NULLs never collide in a unique index.
|
|
71
|
+
migrations.AddConstraint(
|
|
72
|
+
model_name="boardevent",
|
|
73
|
+
constraint=models.UniqueConstraint(
|
|
74
|
+
fields=("project", "seq"), name="boardevent_project_seq_uniq"
|
|
75
|
+
),
|
|
76
|
+
),
|
|
77
|
+
]
|
|
File without changes
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
"""Models for the sync app.
|
|
2
|
+
|
|
3
|
+
The only model here is :class:`SyncBatch`, the idempotency + atomicity
|
|
4
|
+
envelope for a mobile offline **upload** batch (ADR-0082, issue #667). It is
|
|
5
|
+
server infrastructure — the mobile client never pulls it as a domain row — so
|
|
6
|
+
it is a plain ``models.Model`` (not ``VersionedModel``), mirroring the
|
|
7
|
+
transactional-outbox style of ``projects.SprintCloseRequest``.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import uuid
|
|
13
|
+
from datetime import timedelta
|
|
14
|
+
|
|
15
|
+
from django.conf import settings
|
|
16
|
+
from django.db import models
|
|
17
|
+
from django.utils import timezone
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class SyncBatchStatus(models.TextChoices):
|
|
21
|
+
"""Lifecycle of an upload batch envelope (ADR-0082 §D)."""
|
|
22
|
+
|
|
23
|
+
PENDING = "pending", "Pending"
|
|
24
|
+
COMPLETED = "completed", "Completed"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class SyncBatch(models.Model):
|
|
28
|
+
"""Records a mobile upload batch so a retry is a no-op, not a double-apply.
|
|
29
|
+
|
|
30
|
+
A mobile client generates a stable ``client_batch_id`` (UUID) per delta and
|
|
31
|
+
re-uploads the *same* id until it sees an ACK. The first request that wins
|
|
32
|
+
the unique-constraint race applies the delta and snapshots its HTTP response
|
|
33
|
+
here, inside the same transaction as the row writes (all-or-nothing). A
|
|
34
|
+
later request carrying the same id — the lost-ACK retry — returns the stored
|
|
35
|
+
response without re-applying anything.
|
|
36
|
+
|
|
37
|
+
Concurrency is serialized by the ``client_batch_id`` unique constraint:
|
|
38
|
+
Postgres blocks a concurrent duplicate INSERT until the first transaction
|
|
39
|
+
commits or aborts, after which the duplicate either reads the committed row
|
|
40
|
+
(replay) or proceeds (the first attempt rolled back). See
|
|
41
|
+
``sync.views.ProjectSyncView.post`` for the full algorithm.
|
|
42
|
+
|
|
43
|
+
Rows are dedup-relevant only within the freshness window
|
|
44
|
+
(``TRUEPPM_SYNC_BATCH_RETENTION_HOURS``, default 24h); the
|
|
45
|
+
``sync.purge_sync_batches`` Beat task reaps older rows so the table stays
|
|
46
|
+
bounded (ADR-0081 purge convention).
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
|
50
|
+
# Client-generated dedup key. Uniqueness (and every lookup) is scoped to
|
|
51
|
+
# (project, actor_user): a retry always targets the same project endpoint as
|
|
52
|
+
# the same authenticated user, so that composite unique index is a sufficient
|
|
53
|
+
# concurrency backstop, while scoping prevents one project — or one user —
|
|
54
|
+
# replaying another's stored response (the dedup lookup must never cross the
|
|
55
|
+
# project or actor boundary — see views.post, #887/#894).
|
|
56
|
+
client_batch_id = models.UUIDField()
|
|
57
|
+
project = models.ForeignKey(
|
|
58
|
+
"projects.Project",
|
|
59
|
+
on_delete=models.CASCADE,
|
|
60
|
+
related_name="sync_batches",
|
|
61
|
+
)
|
|
62
|
+
# Actor scoping (#894): the stored response body carries task ids,
|
|
63
|
+
# server_versions, and the sync watermark for the rows *this user* pushed.
|
|
64
|
+
# Keying dedup on (project, client_batch_id) alone let any project member
|
|
65
|
+
# replay another member's batch by reusing its client_batch_id and read back
|
|
66
|
+
# that user's response — an information leak across actors. Scoping
|
|
67
|
+
# uniqueness and the replay lookup to the actor closes it: a reused id from a
|
|
68
|
+
# different user is a distinct batch, never a replay of someone else's.
|
|
69
|
+
# Nullable so the migration is backfill-safe for rows written before this
|
|
70
|
+
# field existed (those legacy rows simply never match a new actor-scoped
|
|
71
|
+
# lookup and age out of the freshness window).
|
|
72
|
+
actor_user = models.ForeignKey(
|
|
73
|
+
settings.AUTH_USER_MODEL,
|
|
74
|
+
on_delete=models.CASCADE,
|
|
75
|
+
related_name="sync_batches",
|
|
76
|
+
null=True,
|
|
77
|
+
blank=True,
|
|
78
|
+
)
|
|
79
|
+
status = models.CharField(
|
|
80
|
+
max_length=12,
|
|
81
|
+
choices=SyncBatchStatus.choices,
|
|
82
|
+
default=SyncBatchStatus.PENDING,
|
|
83
|
+
db_index=True,
|
|
84
|
+
)
|
|
85
|
+
# Verbatim success response so a retry replays byte-identically.
|
|
86
|
+
response_body = models.JSONField(default=dict, blank=True)
|
|
87
|
+
response_status = models.PositiveSmallIntegerField(default=200)
|
|
88
|
+
created_at = models.DateTimeField(auto_now_add=True)
|
|
89
|
+
|
|
90
|
+
objects: models.Manager[SyncBatch] = models.Manager()
|
|
91
|
+
|
|
92
|
+
class Meta:
|
|
93
|
+
ordering = ["created_at"]
|
|
94
|
+
constraints = [
|
|
95
|
+
# Actor-scoped uniqueness (#894): two different users may legitimately
|
|
96
|
+
# reuse the same client_batch_id; only a same-(project, actor) duplicate
|
|
97
|
+
# is a replay. Scoping the constraint to the actor prevents one user's
|
|
98
|
+
# batch from blocking — or being replayed by — another's.
|
|
99
|
+
models.UniqueConstraint(
|
|
100
|
+
fields=["project", "actor_user", "client_batch_id"],
|
|
101
|
+
name="syncbatch_project_actor_client_batch_uniq",
|
|
102
|
+
),
|
|
103
|
+
]
|
|
104
|
+
indexes = [
|
|
105
|
+
# Reaper scans by age; the index keeps the nightly purge cheap.
|
|
106
|
+
models.Index(fields=["created_at"], name="syncbatch_created_idx"),
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
def __str__(self) -> str:
|
|
110
|
+
return f"SyncBatch({self.client_batch_id}, {self.status})"
|
|
111
|
+
|
|
112
|
+
def is_fresh(self, *, ttl_hours: int = 24) -> bool:
|
|
113
|
+
"""Return True if this batch is still within the dedup window.
|
|
114
|
+
|
|
115
|
+
A duplicate of a *fresh* completed batch replays the stored response; a
|
|
116
|
+
duplicate of an *expired* batch re-runs the apply (the stale row is
|
|
117
|
+
deleted first). ``ttl_hours`` is supplied by the caller from
|
|
118
|
+
``settings.TRUEPPM_SYNC_BATCH_RETENTION_HOURS``.
|
|
119
|
+
"""
|
|
120
|
+
return self.created_at > timezone.now() - timedelta(hours=ttl_hours)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class BoardEvent(models.Model):
|
|
124
|
+
"""Bounded per-project replay buffer for WebSocket events (ADR-0236, #321).
|
|
125
|
+
|
|
126
|
+
Real-time broadcasts are best-effort: a client that disconnects loses every
|
|
127
|
+
event sent during the gap. Each replayable broadcast persists one ``BoardEvent``
|
|
128
|
+
row here so a reconnecting client can request ``?since=<seq>`` and replay only
|
|
129
|
+
the events it missed — instead of a broad refetch storm — and recover the
|
|
130
|
+
incremental ``task_dates_updated`` CPM splices a refetch-on-focus would drop.
|
|
131
|
+
|
|
132
|
+
Like :class:`SyncBatch`, this is server infrastructure, never pulled as a synced
|
|
133
|
+
domain row, so it is a plain ``models.Model`` (no ``server_version``).
|
|
134
|
+
|
|
135
|
+
**``seq`` is a per-project, dense, commit-ordered sequence (ADR-1285, #4386).**
|
|
136
|
+
It is drawn from the project's :class:`BoardEventSequence` row in the *same*
|
|
137
|
+
transaction as this row's INSERT, so the counter's row lock is held until the
|
|
138
|
+
event commits: within one project, commit order equals allocation order and the
|
|
139
|
+
committed values are 1, 2, 3, … with no holes. That is what lets a client treat
|
|
140
|
+
``seq > last + 1`` as "a frame is missing or still in flight" and ``seq <= last``
|
|
141
|
+
as a genuine duplicate, and lets the consumer prove a replay complete by
|
|
142
|
+
counting rows. The previous design used the global ``BigAutoField`` PK, which
|
|
143
|
+
could not support either: other projects' traffic interleaved it (so the next
|
|
144
|
+
frame on a project was almost never ``last + 1``), two workers' sends could
|
|
145
|
+
arrive in the reverse of allocation order and the later-allocated one would
|
|
146
|
+
make the client drop the other as a duplicate, and the delta between frames
|
|
147
|
+
leaked instance-wide event volume to every project member.
|
|
148
|
+
|
|
149
|
+
``seq`` is NULL on two kinds of row: those written before the #4386 migration,
|
|
150
|
+
which deliberately did not renumber them (``seed_board_event_sequences``), and
|
|
151
|
+
those a pod still running the old code INSERTs during a rolling update. Both are
|
|
152
|
+
live-only. The replay query filters ``seq`` non-null and the allocator never
|
|
153
|
+
counted them, so they neither create a false gap nor get replayed. Rows are reaped past
|
|
154
|
+
``TRUEPPM_BOARD_EVENT_RETENTION_HOURS`` (default 24h) by the
|
|
155
|
+
``sync.purge_board_events`` Beat task (the ADR-0081 purge convention).
|
|
156
|
+
"""
|
|
157
|
+
|
|
158
|
+
# id: implicit BigAutoField PK (DEFAULT_AUTO_FIELD) — row identity only; the
|
|
159
|
+
# wire sequence is ``seq`` (ADR-1285).
|
|
160
|
+
project = models.ForeignKey(
|
|
161
|
+
"projects.Project",
|
|
162
|
+
on_delete=models.CASCADE,
|
|
163
|
+
related_name="board_events",
|
|
164
|
+
)
|
|
165
|
+
seq = models.BigIntegerField(null=True, blank=True, editable=False)
|
|
166
|
+
event_type = models.CharField(max_length=64)
|
|
167
|
+
payload = models.JSONField(default=dict, blank=True)
|
|
168
|
+
created_at = models.DateTimeField(auto_now_add=True)
|
|
169
|
+
|
|
170
|
+
objects: models.Manager[BoardEvent] = models.Manager()
|
|
171
|
+
|
|
172
|
+
class Meta:
|
|
173
|
+
ordering = ["id"]
|
|
174
|
+
constraints = [
|
|
175
|
+
# One event per (project, seq). Its index also serves the replay query
|
|
176
|
+
# ``WHERE project_id=? AND seq > ? AND seq <= ? ORDER BY seq``. NULLs
|
|
177
|
+
# (rolling-update rows, see the class docstring) are distinct in a
|
|
178
|
+
# Postgres unique index, so they never collide.
|
|
179
|
+
models.UniqueConstraint(fields=["project", "seq"], name="boardevent_project_seq_uniq"),
|
|
180
|
+
]
|
|
181
|
+
indexes = [
|
|
182
|
+
# The reaper scans by age; keeps the nightly purge cheap.
|
|
183
|
+
models.Index(fields=["created_at"], name="boardevent_created_idx"),
|
|
184
|
+
]
|
|
185
|
+
|
|
186
|
+
def __str__(self) -> str:
|
|
187
|
+
return f"BoardEvent(seq={self.seq}, {self.event_type}, project={self.project_id})"
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
class BoardEventSequence(models.Model):
|
|
191
|
+
"""Per-project allocator for :attr:`BoardEvent.seq` (ADR-1285, #4386).
|
|
192
|
+
|
|
193
|
+
One row per project that has ever persisted a replayable event, created lazily
|
|
194
|
+
on the first one. ``value`` is the last allocated ``seq`` and therefore also the
|
|
195
|
+
replay head the consumer reports as ``latest_seq``.
|
|
196
|
+
|
|
197
|
+
**Why a row lock and not a PostgreSQL SEQUENCE** — the same reason as
|
|
198
|
+
:class:`ProgramSyncSequence` and the ``sync_seq`` allocator (ADR-0686):
|
|
199
|
+
``nextval()`` is non-transactional, so it would hand out values with no
|
|
200
|
+
relationship to commit order and leave holes on rollback. Allocating by
|
|
201
|
+
``UPDATE … RETURNING`` in the event's own transaction holds this row's lock
|
|
202
|
+
until that transaction commits, which is what makes the committed values dense
|
|
203
|
+
and commit-ordered.
|
|
204
|
+
|
|
205
|
+
**Why its own row and not a column on ``Project``.** ``Project.last_sync_version``
|
|
206
|
+
is held locked for the *whole* apply of a sync upload, and ``Project`` rows are
|
|
207
|
+
also taken ``FOR UPDATE`` by several domain transactions. Broadcasts run in
|
|
208
|
+
``on_commit`` callbacks; putting their allocator on the project row would make
|
|
209
|
+
every broadcast on a project wait behind any of those, and couple a transport
|
|
210
|
+
counter to domain locking. A dedicated row is locked only for the few
|
|
211
|
+
milliseconds of one event INSERT, and nothing else ever locks it, so it cannot
|
|
212
|
+
take part in a lock cycle with the project row.
|
|
213
|
+
"""
|
|
214
|
+
|
|
215
|
+
project = models.OneToOneField(
|
|
216
|
+
"projects.Project",
|
|
217
|
+
on_delete=models.CASCADE,
|
|
218
|
+
primary_key=True,
|
|
219
|
+
related_name="board_event_sequence",
|
|
220
|
+
)
|
|
221
|
+
value = models.BigIntegerField(default=0, editable=False)
|
|
222
|
+
|
|
223
|
+
objects: models.Manager[BoardEventSequence] = models.Manager()
|
|
224
|
+
|
|
225
|
+
def __str__(self) -> str:
|
|
226
|
+
return f"BoardEventSequence(project={self.project_id}, value={self.value})"
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
class ProgramSyncSequence(models.Model):
|
|
230
|
+
"""Installation-wide monotonic allocator for the program sync cursor (ADR-0747).
|
|
231
|
+
|
|
232
|
+
Exactly one row, pk=1. Every synced write to ``Program`` or
|
|
233
|
+
``ProgramMembership`` draws the next value from it and stamps the row's
|
|
234
|
+
``sync_seq``, so those values are totally ordered installation-wide, ``MAX`` is
|
|
235
|
+
a meaningful checkpoint, and ``sync_seq__gt=since`` is a correct delta filter.
|
|
236
|
+
|
|
237
|
+
**Why a table row and not a PostgreSQL SEQUENCE.** ``nextval()`` would avoid
|
|
238
|
+
this row's write lock, and would be wrong. Sequences are non-transactional, so
|
|
239
|
+
they grant no relationship between allocation order and commit order: one
|
|
240
|
+
transaction could allocate 100, a later one allocate 101 and commit first, and a
|
|
241
|
+
pull between the two commits would report 101 and permanently skip 100 — the
|
|
242
|
+
exact defect this replaces, reintroduced as a race. Allocating by ``UPDATE``
|
|
243
|
+
holds this row's write lock until commit, so commit order equals allocation
|
|
244
|
+
order. The lock is the correctness mechanism, not overhead.
|
|
245
|
+
|
|
246
|
+
**Why installation-wide and not per-program.** ``Program`` rows have no single
|
|
247
|
+
owning entity to sequence from the way a ``Task`` has its project (ADR-0686).
|
|
248
|
+
The accessible set is per-user — the union of the caller's programs — so a
|
|
249
|
+
scalar cursor over per-program sequences would reintroduce the same
|
|
250
|
+
hot-row-outruns-cold-row failure one level up. Ordering every program-scoped
|
|
251
|
+
write against one counter is what makes a scalar cursor sound.
|
|
252
|
+
|
|
253
|
+
The cost is that program writes serialize installation-wide. That is acceptable
|
|
254
|
+
because program writes are rare and administrative — create, rename, add or
|
|
255
|
+
remove a member — never a hot path or a bulk import. See ADR-0747 for the
|
|
256
|
+
escape hatch if that ever changes.
|
|
257
|
+
"""
|
|
258
|
+
|
|
259
|
+
#: The single row's primary key. Named so call sites read as intent.
|
|
260
|
+
SINGLETON_PK = 1
|
|
261
|
+
|
|
262
|
+
id = models.BigAutoField(primary_key=True)
|
|
263
|
+
value = models.BigIntegerField(default=0, editable=False)
|
|
264
|
+
|
|
265
|
+
objects: models.Manager[ProgramSyncSequence] = models.Manager()
|
|
266
|
+
|
|
267
|
+
class Meta:
|
|
268
|
+
verbose_name = "program sync sequence"
|
|
269
|
+
verbose_name_plural = "program sync sequence"
|
|
270
|
+
|
|
271
|
+
def __str__(self) -> str:
|
|
272
|
+
return f"ProgramSyncSequence(value={self.value})"
|