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,148 @@
|
|
|
1
|
+
"""Backend-neutral workflow execution interface (ADR-0080 §A).
|
|
2
|
+
|
|
3
|
+
This module is the contract every workflow backend implements — the default
|
|
4
|
+
outbox-composing backend today, a DBOS backend in 1.0. It is deliberately pure
|
|
5
|
+
Python: it imports no engine module (``celery``, ``dbos``, ``temporalio``) and no
|
|
6
|
+
Django, so it can serve as the stable, neutral surface that both workflow
|
|
7
|
+
consumer code and backend implementations depend on.
|
|
8
|
+
|
|
9
|
+
The eight primitives are intentionally narrow. Child workflows, continue-as-new,
|
|
10
|
+
and deterministic-replay guarantees are excluded because they leak engine-specific
|
|
11
|
+
(Temporal) semantics into workflow code and would break the abstraction.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import enum
|
|
17
|
+
from abc import ABC, abstractmethod
|
|
18
|
+
from dataclasses import dataclass
|
|
19
|
+
from datetime import datetime, timedelta
|
|
20
|
+
from typing import Any
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class WorkflowStatus(enum.StrEnum):
|
|
24
|
+
"""Backend-neutral workflow lifecycle status.
|
|
25
|
+
|
|
26
|
+
Values mirror ``trueppm_api.apps.workflow_engine.models.WorkflowStatus`` (the
|
|
27
|
+
default backend's persistence enum) and must stay in sync; they are defined
|
|
28
|
+
here too so consumers can reason about status without importing Django models.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
PENDING = "pending"
|
|
32
|
+
RUNNING = "running"
|
|
33
|
+
SLEEPING = "sleeping"
|
|
34
|
+
COMPLETED = "completed"
|
|
35
|
+
FAILED = "failed"
|
|
36
|
+
CANCELED = "canceled"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass(frozen=True, slots=True)
|
|
40
|
+
class RetryPolicy:
|
|
41
|
+
"""Retry behaviour for an activity run via :meth:`WorkflowBackend.run_activity`.
|
|
42
|
+
|
|
43
|
+
Backend-neutral: each backend translates these fields into its own retry
|
|
44
|
+
mechanism (the default backend maps them onto Celery's retry kwargs).
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
max_attempts: int = 3
|
|
48
|
+
initial_backoff: timedelta = timedelta(seconds=1)
|
|
49
|
+
backoff_multiplier: float = 2.0
|
|
50
|
+
max_backoff: timedelta = timedelta(minutes=5)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@dataclass(frozen=True, slots=True)
|
|
54
|
+
class HistoryEvent:
|
|
55
|
+
"""One entry in a workflow's ordered, append-only history."""
|
|
56
|
+
|
|
57
|
+
seq: int
|
|
58
|
+
event_type: str
|
|
59
|
+
payload: dict[str, Any]
|
|
60
|
+
occurred_at: datetime
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@dataclass(frozen=True, slots=True)
|
|
64
|
+
class WorkflowState:
|
|
65
|
+
"""A point-in-time read model of a workflow instance.
|
|
66
|
+
|
|
67
|
+
Returned by :meth:`WorkflowBackend.get_workflow_state`. Intentionally a plain
|
|
68
|
+
value object, not a Django model, so consumers never bind to the default
|
|
69
|
+
backend's persistence layer.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
workflow_id: str
|
|
73
|
+
name: str
|
|
74
|
+
status: WorkflowStatus
|
|
75
|
+
result: dict[str, Any] | None = None
|
|
76
|
+
error: str = ""
|
|
77
|
+
created_at: datetime | None = None
|
|
78
|
+
updated_at: datetime | None = None
|
|
79
|
+
completed_at: datetime | None = None
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class WorkflowBackend(ABC):
|
|
83
|
+
"""The eight-primitive workflow execution contract (ADR-0080 §A).
|
|
84
|
+
|
|
85
|
+
Implemented by each backend (default outbox-composing; future DBOS). Workflow
|
|
86
|
+
consumer code never calls a backend directly — it goes through
|
|
87
|
+
:mod:`trueppm_api.workflows.services`, which resolves the configured backend.
|
|
88
|
+
There is deliberately no ``_backend`` parameter on any method: if workflow
|
|
89
|
+
code ever needed to know which backend it runs on, the abstraction would have
|
|
90
|
+
already failed (ADR-0080 §E).
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
@abstractmethod
|
|
94
|
+
def start_workflow(
|
|
95
|
+
self,
|
|
96
|
+
name: str,
|
|
97
|
+
input: dict[str, Any],
|
|
98
|
+
*,
|
|
99
|
+
idempotency_key: str | None = None,
|
|
100
|
+
wait_for_completion: bool = False,
|
|
101
|
+
) -> str:
|
|
102
|
+
"""Start a workflow and return its id.
|
|
103
|
+
|
|
104
|
+
Fire-and-forget by default (``wait_for_completion=False``); blocking on
|
|
105
|
+
completion defeats the durability guarantee and is reserved for
|
|
106
|
+
bounded-short workflows. ``idempotency_key`` defaults to a deterministic
|
|
107
|
+
hash of ``name`` + ``input`` so a retried start does not duplicate work.
|
|
108
|
+
"""
|
|
109
|
+
|
|
110
|
+
@abstractmethod
|
|
111
|
+
def signal_workflow(self, workflow_id: str, signal: str, payload: dict[str, Any]) -> None:
|
|
112
|
+
"""Deliver a named signal to a workflow.
|
|
113
|
+
|
|
114
|
+
Durable: a signal that arrives before the workflow waits for it is queued,
|
|
115
|
+
not dropped.
|
|
116
|
+
"""
|
|
117
|
+
|
|
118
|
+
@abstractmethod
|
|
119
|
+
def query_workflow(self, workflow_id: str, query: str, args: dict[str, Any]) -> Any:
|
|
120
|
+
"""Run a named read-only query against a workflow's current state."""
|
|
121
|
+
|
|
122
|
+
@abstractmethod
|
|
123
|
+
def get_workflow_state(self, workflow_id: str) -> WorkflowState:
|
|
124
|
+
"""Return a point-in-time read model of the workflow."""
|
|
125
|
+
|
|
126
|
+
@abstractmethod
|
|
127
|
+
def cancel_workflow(self, workflow_id: str, reason: str = "") -> None:
|
|
128
|
+
"""Request cancellation of a workflow, recording an optional reason."""
|
|
129
|
+
|
|
130
|
+
@abstractmethod
|
|
131
|
+
def sleep(self, workflow_id: str, duration: timedelta) -> None:
|
|
132
|
+
"""Durable timer: suspend the workflow until ``duration`` has elapsed."""
|
|
133
|
+
|
|
134
|
+
@abstractmethod
|
|
135
|
+
def run_activity(
|
|
136
|
+
self, name: str, input: dict[str, Any], retry_policy: RetryPolicy | None = None
|
|
137
|
+
) -> Any:
|
|
138
|
+
"""Execute a named activity (the side-effect boundary) with retries.
|
|
139
|
+
|
|
140
|
+
Called from within a workflow's execution; the backend resolves the
|
|
141
|
+
current workflow from execution context. Idempotent at the
|
|
142
|
+
``(workflow, activity_name, input)`` level — a replayed activity returns
|
|
143
|
+
its previously recorded result instead of re-executing the side effect.
|
|
144
|
+
"""
|
|
145
|
+
|
|
146
|
+
@abstractmethod
|
|
147
|
+
def get_history(self, workflow_id: str) -> list[HistoryEvent]:
|
|
148
|
+
"""Return the workflow's ordered, append-only history."""
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""Workflow definition registry (ADR-0080 §A).
|
|
2
|
+
|
|
3
|
+
Workflow authors register a :class:`WorkflowDefinition` under a unique name; the
|
|
4
|
+
engine resolves it at start time. This module is part of the backend-neutral
|
|
5
|
+
surface — it must never import ``celery``, ``dbos``, or ``temporalio``. A
|
|
6
|
+
definition describes *what* runs (an ordered chain of steps with optional
|
|
7
|
+
compensation, the ``TaskChain`` model from #65); the backend decides *how*.
|
|
8
|
+
|
|
9
|
+
The declarative step list is what keeps authoring backend-portable: the default
|
|
10
|
+
Celery+outbox backend, the DBOS adapter, and a future Temporal adapter can each
|
|
11
|
+
execute the same definition. See ADR-0080 §A "Authoring model".
|
|
12
|
+
|
|
13
|
+
Registration mirrors the integration ``ProviderRegistry`` pattern (ADR-0049):
|
|
14
|
+
OSS definitions register in ``WorkflowEngineConfig.ready()``; enterprise definitions
|
|
15
|
+
register from their own ``AppConfig.ready()`` — same hook, no ``if enterprise``.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
from collections.abc import Callable
|
|
21
|
+
from dataclasses import dataclass
|
|
22
|
+
from typing import Any
|
|
23
|
+
|
|
24
|
+
# An activity is a callable taking a context dict and returning a JSON-able
|
|
25
|
+
# result (or None). The engine wraps every activity execution in once-and-only-once
|
|
26
|
+
# semantics, so an activity must be safe to *record* once even if dispatched twice.
|
|
27
|
+
Activity = Callable[[dict[str, Any]], dict[str, Any] | None]
|
|
28
|
+
|
|
29
|
+
# A compensation undoes a previously-completed step during saga rollback. It
|
|
30
|
+
# receives the same context the step's activity received. Best-effort: failures
|
|
31
|
+
# are logged, not re-raised, so one failed rollback does not strand the others.
|
|
32
|
+
Compensation = Callable[[dict[str, Any]], None]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclass(frozen=True, slots=True)
|
|
36
|
+
class WorkflowStep:
|
|
37
|
+
"""One step in a workflow's chain: an activity plus optional compensation.
|
|
38
|
+
|
|
39
|
+
``name`` is unique within a definition and is the activity-name half of the
|
|
40
|
+
once-and-only-once key ``(workflow, activity_name, input_hash)``.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
name: str
|
|
44
|
+
activity: Activity
|
|
45
|
+
compensate: Compensation | None = None
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class WorkflowDefinition:
|
|
49
|
+
"""Base class for a registered workflow (ADR-0080 §A).
|
|
50
|
+
|
|
51
|
+
Subclasses set ``name`` and implement :meth:`build_steps` to return the
|
|
52
|
+
ordered chain for a given input. The v1 engine executes the chain
|
|
53
|
+
sequentially, compensating completed steps in reverse on failure. Override
|
|
54
|
+
:meth:`on_query` to answer ``query_workflow`` calls.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
name: str
|
|
58
|
+
|
|
59
|
+
def build_steps(self, workflow_input: dict[str, Any]) -> list[WorkflowStep]:
|
|
60
|
+
"""Return the ordered steps for this workflow run.
|
|
61
|
+
|
|
62
|
+
Pure and deterministic given ``workflow_input`` — the engine may rebuild
|
|
63
|
+
the chain on a redelivered step, so the same input must yield the same
|
|
64
|
+
steps in the same order.
|
|
65
|
+
"""
|
|
66
|
+
raise NotImplementedError
|
|
67
|
+
|
|
68
|
+
def on_query(self, query: str, args: dict[str, Any]) -> Any:
|
|
69
|
+
"""Answer a named read-only query against the workflow (optional)."""
|
|
70
|
+
raise NotImplementedError(f"workflow {self.name!r} defines no query handler")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class WorkflowRegistry:
|
|
74
|
+
"""Name → definition registry, mirroring integrations' ``ProviderRegistry``.
|
|
75
|
+
|
|
76
|
+
A duplicate name raises rather than silently overwriting, so two apps cannot
|
|
77
|
+
both claim a workflow name without a loud failure at registration time.
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
def __init__(self) -> None:
|
|
81
|
+
self._registry: dict[str, WorkflowDefinition] = {}
|
|
82
|
+
|
|
83
|
+
def register(self, definition: WorkflowDefinition) -> WorkflowDefinition:
|
|
84
|
+
name = definition.name
|
|
85
|
+
if name in self._registry:
|
|
86
|
+
raise ValueError(f"workflow {name!r} is already registered")
|
|
87
|
+
self._registry[name] = definition
|
|
88
|
+
return definition
|
|
89
|
+
|
|
90
|
+
def get(self, name: str) -> WorkflowDefinition:
|
|
91
|
+
try:
|
|
92
|
+
return self._registry[name]
|
|
93
|
+
except KeyError:
|
|
94
|
+
raise KeyError(f"no workflow registered under {name!r}") from None
|
|
95
|
+
|
|
96
|
+
def all(self) -> dict[str, WorkflowDefinition]:
|
|
97
|
+
"""Return a copy of the registered definitions (used by the contract test)."""
|
|
98
|
+
return dict(self._registry)
|
|
99
|
+
|
|
100
|
+
def clear(self) -> None:
|
|
101
|
+
"""Reset the registry — test helper only."""
|
|
102
|
+
self._registry.clear()
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
# Process-wide singleton. Workflow definitions register against this.
|
|
106
|
+
WORKFLOWS = WorkflowRegistry()
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""Public service layer for workflow execution (ADR-0080 §Implementation Notes 4).
|
|
2
|
+
|
|
3
|
+
All workflow starts, signals, queries, and inspections from view or consumer code
|
|
4
|
+
go through these module-level functions. They resolve the configured backend and
|
|
5
|
+
delegate. Never import or instantiate a backend class directly — the indirection
|
|
6
|
+
here is what keeps consumer code backend-neutral (ADR-0080 §E).
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from datetime import timedelta
|
|
12
|
+
from functools import lru_cache
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
from django.conf import settings
|
|
16
|
+
from django.utils.module_loading import import_string
|
|
17
|
+
|
|
18
|
+
from trueppm_api.workflows.interface import (
|
|
19
|
+
HistoryEvent,
|
|
20
|
+
RetryPolicy,
|
|
21
|
+
WorkflowBackend,
|
|
22
|
+
WorkflowState,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
DEFAULT_BACKEND = "trueppm_api.workflows.backends.default.DefaultWorkflowBackend"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@lru_cache(maxsize=1)
|
|
29
|
+
def get_backend() -> WorkflowBackend:
|
|
30
|
+
"""Resolve and cache the configured workflow backend.
|
|
31
|
+
|
|
32
|
+
Reads ``settings.WORKFLOW_BACKEND`` (a dotted path to a
|
|
33
|
+
:class:`~trueppm_api.workflows.interface.WorkflowBackend` subclass),
|
|
34
|
+
defaulting to the outbox-composing default backend. Cached for the process
|
|
35
|
+
lifetime; tests that swap backends must call ``get_backend.cache_clear()``.
|
|
36
|
+
"""
|
|
37
|
+
dotted = getattr(settings, "WORKFLOW_BACKEND", DEFAULT_BACKEND)
|
|
38
|
+
backend_cls: type[WorkflowBackend] = import_string(dotted)
|
|
39
|
+
return backend_cls()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def start_workflow(
|
|
43
|
+
name: str,
|
|
44
|
+
input: dict[str, Any],
|
|
45
|
+
*,
|
|
46
|
+
idempotency_key: str | None = None,
|
|
47
|
+
wait_for_completion: bool = False,
|
|
48
|
+
) -> str:
|
|
49
|
+
"""Start a workflow; see :meth:`WorkflowBackend.start_workflow`."""
|
|
50
|
+
return get_backend().start_workflow(
|
|
51
|
+
name,
|
|
52
|
+
input,
|
|
53
|
+
idempotency_key=idempotency_key,
|
|
54
|
+
wait_for_completion=wait_for_completion,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def signal_workflow(workflow_id: str, signal: str, payload: dict[str, Any]) -> None:
|
|
59
|
+
"""Deliver a signal; see :meth:`WorkflowBackend.signal_workflow`."""
|
|
60
|
+
get_backend().signal_workflow(workflow_id, signal, payload)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def query_workflow(workflow_id: str, query: str, args: dict[str, Any]) -> Any:
|
|
64
|
+
"""Query a workflow; see :meth:`WorkflowBackend.query_workflow`."""
|
|
65
|
+
return get_backend().query_workflow(workflow_id, query, args)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def get_workflow_state(workflow_id: str) -> WorkflowState:
|
|
69
|
+
"""Fetch workflow state; see :meth:`WorkflowBackend.get_workflow_state`."""
|
|
70
|
+
return get_backend().get_workflow_state(workflow_id)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def cancel_workflow(workflow_id: str, reason: str = "") -> None:
|
|
74
|
+
"""Cancel a workflow; see :meth:`WorkflowBackend.cancel_workflow`."""
|
|
75
|
+
get_backend().cancel_workflow(workflow_id, reason)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def sleep(workflow_id: str, duration: timedelta) -> None:
|
|
79
|
+
"""Durable sleep; see :meth:`WorkflowBackend.sleep`."""
|
|
80
|
+
get_backend().sleep(workflow_id, duration)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def run_activity(name: str, input: dict[str, Any], retry_policy: RetryPolicy | None = None) -> Any:
|
|
84
|
+
"""Run an activity; see :meth:`WorkflowBackend.run_activity`."""
|
|
85
|
+
return get_backend().run_activity(name, input, retry_policy)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def get_history(workflow_id: str) -> list[HistoryEvent]:
|
|
89
|
+
"""Fetch history; see :meth:`WorkflowBackend.get_history`."""
|
|
90
|
+
return get_backend().get_history(workflow_id)
|
trueppm_api/wsgi.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""WSGI application (used by runserver in non-ASGI contexts)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
from django.core.wsgi import get_wsgi_application
|
|
8
|
+
|
|
9
|
+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "trueppm_api.settings.dev")
|
|
10
|
+
|
|
11
|
+
application = get_wsgi_application()
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: trueppm-api
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: TruePPM Django REST API — projects, tasks, scheduling, real-time collaboration
|
|
5
|
+
Author: Kelly Hair
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
License-File: NOTICE
|
|
9
|
+
License-File: NOTICES
|
|
10
|
+
License-File: licenses/GPL-3.0.txt
|
|
11
|
+
License-File: licenses/LGPL-3.0.txt
|
|
12
|
+
License-File: licenses/MPL-2.0.txt
|
|
13
|
+
Requires-Python: >=3.11
|
|
14
|
+
Requires-Dist: boto3<2.0,>=1.35
|
|
15
|
+
Requires-Dist: celery<6.0,>=5.6
|
|
16
|
+
Requires-Dist: channels-redis<5.0,>=4.0
|
|
17
|
+
Requires-Dist: channels<5.0,>=4.0
|
|
18
|
+
Requires-Dist: cryptography<51,>=50.0.0
|
|
19
|
+
Requires-Dist: defusedxml<0.8,>=0.7
|
|
20
|
+
Requires-Dist: django-allauth[socialaccount]<66.0,>=65.18.0
|
|
21
|
+
Requires-Dist: django-environ<1.0,>=0.11
|
|
22
|
+
Requires-Dist: django-simple-history<4.0,>=3.7
|
|
23
|
+
Requires-Dist: django-storages<2.0,>=1.14.6
|
|
24
|
+
Requires-Dist: django<6.0,>=5.2.17
|
|
25
|
+
Requires-Dist: djangorestframework-simplejwt<6.0,>=5.3.1
|
|
26
|
+
Requires-Dist: djangorestframework<3.19,>=3.18.2
|
|
27
|
+
Requires-Dist: dnspython<3.0,>=2.9.0
|
|
28
|
+
Requires-Dist: drf-spectacular[sidecar]==0.30.0
|
|
29
|
+
Requires-Dist: jsonschema<5.0,>=4.21
|
|
30
|
+
Requires-Dist: msgpack<2.0,>=1.2.3
|
|
31
|
+
Requires-Dist: openpyxl<4.0,>=3.1
|
|
32
|
+
Requires-Dist: opentelemetry-exporter-otlp<2,>=1.45.1
|
|
33
|
+
Requires-Dist: opentelemetry-instrumentation-asgi<1,>=0.66b1
|
|
34
|
+
Requires-Dist: opentelemetry-instrumentation-celery<1,>=0.66b1
|
|
35
|
+
Requires-Dist: opentelemetry-instrumentation-django<1,>=0.66b1
|
|
36
|
+
Requires-Dist: opentelemetry-instrumentation-psycopg<1,>=0.66b1
|
|
37
|
+
Requires-Dist: opentelemetry-sdk<2,>=1.45.1
|
|
38
|
+
Requires-Dist: packaging>=24.0
|
|
39
|
+
Requires-Dist: psycopg<4.0,>=3.1.8
|
|
40
|
+
Requires-Dist: pyjwt[crypto]<3.0,>=2.14
|
|
41
|
+
Requires-Dist: python-json-logger<3.0,>=2.0
|
|
42
|
+
Requires-Dist: redis<6.5,>=6.4
|
|
43
|
+
Requires-Dist: trueppm-scheduler<0.5,>=0.4.0rc2
|
|
44
|
+
Requires-Dist: uvicorn[standard]<1.0,>=0.29
|
|
45
|
+
Requires-Dist: whitenoise<7.0,>=6.0
|
|
46
|
+
Provides-Extra: binary
|
|
47
|
+
Requires-Dist: psycopg[binary]<4.0,>=3.1.8; extra == 'binary'
|
|
48
|
+
Provides-Extra: c
|
|
49
|
+
Requires-Dist: psycopg[c]<4.0,>=3.1.8; extra == 'c'
|
|
50
|
+
Provides-Extra: dev
|
|
51
|
+
Requires-Dist: diff-cover<10.0,>=9.0; extra == 'dev'
|
|
52
|
+
Requires-Dist: django-stubs[compatible-mypy]==6.1.0; extra == 'dev'
|
|
53
|
+
Requires-Dist: djangorestframework-stubs[compatible-mypy]==3.18.1; extra == 'dev'
|
|
54
|
+
Requires-Dist: mutmut==3.8.0; extra == 'dev'
|
|
55
|
+
Requires-Dist: mypy==1.20.2; extra == 'dev'
|
|
56
|
+
Requires-Dist: psycopg[binary]<4.0,>=3.1.8; extra == 'dev'
|
|
57
|
+
Requires-Dist: pytest-asyncio<2.0,>=0.23; extra == 'dev'
|
|
58
|
+
Requires-Dist: pytest-cov<8.0,>=4.0; extra == 'dev'
|
|
59
|
+
Requires-Dist: pytest-django<5.0,>=4.8; extra == 'dev'
|
|
60
|
+
Requires-Dist: pytest-socket<1.0,>=0.8; extra == 'dev'
|
|
61
|
+
Requires-Dist: pytest-split<1.0,>=0.9; extra == 'dev'
|
|
62
|
+
Requires-Dist: pytest-timeout<3.0,>=2.4; extra == 'dev'
|
|
63
|
+
Requires-Dist: pytest-xdist<4.0,>=3.6; extra == 'dev'
|
|
64
|
+
Requires-Dist: pytest<10.0,>=8.0; extra == 'dev'
|
|
65
|
+
Requires-Dist: ruff<1.0,>=0.8; extra == 'dev'
|
|
66
|
+
Requires-Dist: testcontainers[postgres]<5.0,>=4.7; extra == 'dev'
|
|
67
|
+
Provides-Extra: fuzz
|
|
68
|
+
Requires-Dist: schemathesis<5.0,>=4.0; extra == 'fuzz'
|
|
69
|
+
Description-Content-Type: text/markdown
|
|
70
|
+
|
|
71
|
+
# trueppm-api
|
|
72
|
+
|
|
73
|
+
[](https://pypi.org/project/trueppm-api/)
|
|
74
|
+
[](https://pypi.org/project/trueppm-api/)
|
|
75
|
+
[](https://gitlab.com/trueppm/trueppm/-/pipelines)
|
|
76
|
+
[](https://www.apache.org/licenses/LICENSE-2.0)
|
|
77
|
+
|
|
78
|
+
Django REST + WebSocket backend for [TruePPM](https://trueppm.com) — projects, tasks,
|
|
79
|
+
critical-path scheduling, agile boards and sprints, offline sync, and real-time
|
|
80
|
+
collaboration.
|
|
81
|
+
|
|
82
|
+
## Is this package for you?
|
|
83
|
+
|
|
84
|
+
Most people should **not** `pip install` this directly. If you want to run TruePPM,
|
|
85
|
+
start from the [quickstart guide](https://docs.trueppm.com/getting-started/quickstart/)
|
|
86
|
+
(`docker compose up`) or the [Helm chart](https://gitlab.com/trueppm/trueppm/-/tree/main/packages/helm) —
|
|
87
|
+
both wire up PostgreSQL, Valkey, the web frontend, and a Celery worker for you.
|
|
88
|
+
|
|
89
|
+
This package exists on PyPI for two narrower audiences:
|
|
90
|
+
|
|
91
|
+
- **Downstream projects that depend on the OSS backend as a library** — most notably
|
|
92
|
+
[TruePPM Enterprise](https://trueppm.com) (proprietary, separate repo), which pins an
|
|
93
|
+
exact `trueppm-api` release instead of a git submodule or path dependency. See
|
|
94
|
+
[Using this as a dependency](#using-this-as-a-dependency).
|
|
95
|
+
- **Operators who want to run the API standalone** — against Postgres/Valkey you
|
|
96
|
+
already manage, without Docker Compose or the bundled frontend. See
|
|
97
|
+
[Standalone quickstart](#standalone-quickstart).
|
|
98
|
+
|
|
99
|
+
If neither of those is you, the linked quickstart is a better starting point.
|
|
100
|
+
|
|
101
|
+
## Requirements
|
|
102
|
+
|
|
103
|
+
- **Python 3.11+**
|
|
104
|
+
- **PostgreSQL 16+**, with the `ltree`, `pg_trgm`, and `btree_gist` extensions
|
|
105
|
+
installable by the connecting role (migrations run `CREATE EXTENSION IF NOT EXISTS`
|
|
106
|
+
for each — the role needs `CREATEDB`/superuser on a fresh database, or ask your DBA
|
|
107
|
+
to pre-create the extensions)
|
|
108
|
+
- **Valkey 8+** (or Redis 7+, wire-compatible) — backs the WebSocket channel layer and
|
|
109
|
+
the Celery broker/result backend
|
|
110
|
+
- **A Celery worker**, if you want anything that runs off the request/response cycle:
|
|
111
|
+
async schedule recalculation, notifications, MS Project/Jira/CSV import jobs. The
|
|
112
|
+
API serves reads and writes without one, but background jobs will queue and never run.
|
|
113
|
+
- **S3-compatible object storage**, in production only, for task attachments. Local
|
|
114
|
+
disk storage is the dev default and is explicitly refused at boot in
|
|
115
|
+
`trueppm_api.settings.prod` unless you opt in (fine for local/single-node
|
|
116
|
+
evaluation, not for anything you intend to keep).
|
|
117
|
+
|
|
118
|
+
## Install
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
# Development — precompiled psycopg wheel, no compiler or system libpq needed
|
|
122
|
+
pip install "trueppm-api[binary]"
|
|
123
|
+
|
|
124
|
+
# Production — links against the system libpq, so OS security patches reach
|
|
125
|
+
# the driver without a new release of this package
|
|
126
|
+
pip install "trueppm-api[c]"
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Extras:
|
|
130
|
+
|
|
131
|
+
| Extra | Use it for |
|
|
132
|
+
|---|---|
|
|
133
|
+
| `binary` | Local dev / quick-start psycopg (precompiled wheel, bundles its own libpq) |
|
|
134
|
+
| `c` | Production psycopg (compiled against the system libpq) |
|
|
135
|
+
| `dev` | Test tooling (pytest, mypy, ruff, testcontainers) — installed from a source checkout, not by consumers |
|
|
136
|
+
| `fuzz` | Schemathesis, for OpenAPI-schema-driven fuzz testing — installed from a source checkout, not by consumers |
|
|
137
|
+
|
|
138
|
+
Pick one of `binary`/`c`. The base install already pulls plain `psycopg`, whose
|
|
139
|
+
pure-Python core binds to `libpq` via `ctypes` at runtime — that only works if a
|
|
140
|
+
system `libpq` is already installed and discoverable, so `binary` (bundles its
|
|
141
|
+
own) or `c` (links the one you installed) is the reliable path.
|
|
142
|
+
|
|
143
|
+
## Standalone quickstart
|
|
144
|
+
|
|
145
|
+
This runs the API by itself against Postgres/Valkey instances you already have —
|
|
146
|
+
no Docker Compose, no frontend. Five minutes if those two services are already up.
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
pip install "trueppm-api[binary]"
|
|
150
|
+
|
|
151
|
+
export DJANGO_SETTINGS_MODULE=trueppm_api.settings.dev
|
|
152
|
+
export TRUEPPM_ALLOW_DEV_SETTINGS=1 # dev settings refuse to import without this
|
|
153
|
+
export SECRET_KEY="$(python3 -c 'import secrets; print(secrets.token_urlsafe(48))')"
|
|
154
|
+
export DATABASE_URL="postgres://trueppm:trueppm@localhost:5432/trueppm"
|
|
155
|
+
export REDIS_URL="redis://localhost:6379"
|
|
156
|
+
|
|
157
|
+
django-admin migrate
|
|
158
|
+
django-admin createsuperuser
|
|
159
|
+
django-admin runserver 0.0.0.0:8000
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Then:
|
|
163
|
+
|
|
164
|
+
- `http://localhost:8000/api/v1/health/` — liveness check, no auth
|
|
165
|
+
- `http://localhost:8000/api/docs/` — interactive Swagger UI (served from `[sidecar]`
|
|
166
|
+
static assets, so it works offline / behind a strict CSP)
|
|
167
|
+
- `http://localhost:8000/admin/` — Django admin, using the superuser you just created
|
|
168
|
+
|
|
169
|
+
`trueppm_api.settings.dev` hardcodes `ALLOWED_HOSTS = ["*"]` and open (`AllowAny`)
|
|
170
|
+
API permissions, so it refuses to even import without `TRUEPPM_ALLOW_DEV_SETTINGS=1`
|
|
171
|
+
set (or a test runner active) — that guard is what the env var above satisfies.
|
|
172
|
+
**Do not use it past localhost.** For anything reachable over a network, switch to
|
|
173
|
+
`trueppm_api.settings.prod`, which enforces `ALLOWED_HOSTS`, a real `SECRET_KEY`,
|
|
174
|
+
and durable attachment storage at import time — it refuses to boot rather than
|
|
175
|
+
silently run insecure. `manage.py` (the entry point the full repo uses) is a thin
|
|
176
|
+
wrapper around `django-admin` that defaults `DJANGO_SETTINGS_MODULE` to
|
|
177
|
+
`trueppm_api.settings.dev`; installed via pip you use `django-admin` directly, as
|
|
178
|
+
above, and set the setting explicitly.
|
|
179
|
+
|
|
180
|
+
For the full experience — the React frontend, a Celery worker, WebSocket
|
|
181
|
+
broadcasts, seeded demo data — use the [Docker Compose
|
|
182
|
+
quickstart](https://docs.trueppm.com/getting-started/quickstart/) instead; it
|
|
183
|
+
runs this same package, wired up for you.
|
|
184
|
+
|
|
185
|
+
Every environment variable this package reads, including production-only ones
|
|
186
|
+
(object storage, OIDC single sign-on, OpenTelemetry, rate limits) is documented at
|
|
187
|
+
**[docs.trueppm.com/administration/configuration](https://docs.trueppm.com/administration/configuration/)**.
|
|
188
|
+
`SECRET_KEY`, `DATABASE_URL`, and `REDIS_URL` above are the only three with no safe
|
|
189
|
+
default outside of `trueppm_api.settings.dev`.
|
|
190
|
+
|
|
191
|
+
## Using this as a dependency
|
|
192
|
+
|
|
193
|
+
Pin an exact release the same way you'd pin any other PyPI package:
|
|
194
|
+
|
|
195
|
+
```toml
|
|
196
|
+
# pyproject.toml
|
|
197
|
+
[project]
|
|
198
|
+
dependencies = [
|
|
199
|
+
"trueppm-api==0.4.0",
|
|
200
|
+
]
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
pip install "trueppm-api[c]==0.4.0"
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
`import trueppm_api; trueppm_api.__version__` reflects the installed distribution
|
|
208
|
+
version (read from package metadata, not a hand-maintained string), so it always
|
|
209
|
+
agrees with `pip show trueppm-api`.
|
|
210
|
+
|
|
211
|
+
`trueppm_api.settings.base` is written to be extended: a downstream project's own
|
|
212
|
+
settings module can do `from trueppm_api.settings.base import *` and layer
|
|
213
|
+
additional `INSTALLED_APPS`, middleware, or DRF settings on top, the same pattern
|
|
214
|
+
`trueppm_api.settings.prod` itself uses. This is how TruePPM Enterprise adds its
|
|
215
|
+
portfolio-governance apps without forking the OSS backend.
|
|
216
|
+
|
|
217
|
+
## Versioning and releases
|
|
218
|
+
|
|
219
|
+
**The version number tracks the whole TruePPM platform release, not this package
|
|
220
|
+
independently.** `0.4.0` on PyPI corresponds to git tag `v0.4.0` in the
|
|
221
|
+
[trueppm-suite](https://gitlab.com/trueppm/trueppm) monorepo — the same release
|
|
222
|
+
that produced the `api`/`web` Docker images and the Helm chart at that version.
|
|
223
|
+
There is no separate changelog or release cadence for `trueppm-api` alone; see the
|
|
224
|
+
[root `CHANGELOG.md`](https://gitlab.com/trueppm/trueppm/-/blob/main/CHANGELOG.md)
|
|
225
|
+
for what changed in any given release.
|
|
226
|
+
|
|
227
|
+
Every `v*` tag publishes this package to PyPI automatically (CI job
|
|
228
|
+
`api:publish:pypi`), alongside the Docker images and the Helm chart. `@trueppm/web`
|
|
229
|
+
is not published to npm — it is an application bundle, not a library (see the
|
|
230
|
+
[root README's Published artifacts table](https://gitlab.com/trueppm/trueppm#published-artifacts)). As of #3943, this job authenticates via **PyPI Trusted
|
|
231
|
+
Publishing** (GitLab OIDC) and signs [PEP 740](https://peps.python.org/pep-0740/)
|
|
232
|
+
attestations, the same as `trueppm-scheduler` and `trueppm-mcp` — there is no
|
|
233
|
+
static upload token on the publish path. That release job is unproven until
|
|
234
|
+
the next `v*` tag, so versions through `0.4.0-beta.3` predate it and were
|
|
235
|
+
published with a static token, with no attestation. Pre-release versions (`aN`/`bN`/`rcN`) are real
|
|
236
|
+
releases of whatever that tag shipped, not throwaway snapshots — TruePPM is
|
|
237
|
+
pre-1.0 and ships its entire release line as alphas/betas/RCs, per
|
|
238
|
+
[SECURITY.md](https://gitlab.com/trueppm/trueppm/-/blob/main/SECURITY.md).
|
|
239
|
+
|
|
240
|
+
Before 1.0, breaking changes to this package's Python API (settings shape, model
|
|
241
|
+
fields, management commands) can happen between releases without a deprecation
|
|
242
|
+
window — the published contract that *is* stable pre-1.0 is the HTTP/WebSocket API
|
|
243
|
+
surface, documented at
|
|
244
|
+
[docs.trueppm.com/api/stability](https://docs.trueppm.com/api/stability/). If
|
|
245
|
+
you're pinning this package as a library dependency rather than talking to a
|
|
246
|
+
running instance over HTTP, expect to read the changelog on every bump.
|
|
247
|
+
|
|
248
|
+
## Documentation
|
|
249
|
+
|
|
250
|
+
- **Full docs**: [docs.trueppm.com](https://docs.trueppm.com)
|
|
251
|
+
- **API reference**: [docs.trueppm.com/api/reference](https://docs.trueppm.com/api/reference/)
|
|
252
|
+
- **Configuration reference**: [docs.trueppm.com/administration/configuration](https://docs.trueppm.com/administration/configuration/)
|
|
253
|
+
- **Source / issues**: [gitlab.com/trueppm/trueppm](https://gitlab.com/trueppm/trueppm)
|
|
254
|
+
|
|
255
|
+
## Tests
|
|
256
|
+
|
|
257
|
+
From a source checkout:
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
cd packages/api
|
|
261
|
+
pip install -e ".[binary,dev]"
|
|
262
|
+
pytest
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Most tests need a real PostgreSQL (for `ltree`/`pg_trgm` queries) — the repo's
|
|
266
|
+
`docker compose up` provides one; `testcontainers[postgres]` (a `dev` extra) can
|
|
267
|
+
also spin one up ephemerally.
|
|
268
|
+
|
|
269
|
+
## License
|
|
270
|
+
|
|
271
|
+
Apache 2.0 — see [LICENSE](https://gitlab.com/trueppm/trueppm/-/blob/main/LICENSE).
|
|
272
|
+
Copyright MacroDream, LLC and contributors — see
|
|
273
|
+
[NOTICE](https://gitlab.com/trueppm/trueppm/-/blob/main/NOTICE).
|