ecoportal-api-graphql 1.3.16 → 2.2.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +746 -6
- data/LICENSE +21 -21
- data/README.md +24 -24
- data/lib/ecoportal/api/common/graphql/auth_service.rb +115 -115
- data/lib/ecoportal/api/common/graphql/class_helpers.rb +46 -46
- data/lib/ecoportal/api/common/graphql/client.rb +69 -69
- data/lib/ecoportal/api/common/graphql/hash_helpers.rb +105 -105
- data/lib/ecoportal/api/common/graphql/http_client.rb +85 -2
- data/lib/ecoportal/api/common/graphql/model/as_input.rb +54 -54
- data/lib/ecoportal/api/common/graphql/model/diffable/classic_diff_service.rb +49 -49
- data/lib/ecoportal/api/common/graphql/model/diffable/diff_service.rb +188 -188
- data/lib/ecoportal/api/common/graphql/model/diffable/hash_diff.rb +55 -55
- data/lib/ecoportal/api/common/graphql/model/diffable/hash_diff_nesting.rb +295 -295
- data/lib/ecoportal/api/common/graphql/model/diffable/leaf_diff_service.rb +97 -0
- data/lib/ecoportal/api/common/graphql/model/diffable.rb +1 -0
- data/lib/ecoportal/api/common/graphql/model.rb +17 -17
- data/lib/ecoportal/api/common/graphql/patches.rb +1 -1
- data/lib/ecoportal/api/common/graphql/query_integration.rb +45 -45
- data/lib/ecoportal/api/common/graphql.rb +16 -16
- data/lib/ecoportal/api/common.graphql.rb +8 -8
- data/lib/ecoportal/api/graphql/base/action.rb +1 -1
- data/lib/ecoportal/api/graphql/base/action_category.rb +15 -15
- data/lib/ecoportal/api/graphql/base/action_event.rb +23 -0
- data/lib/ecoportal/api/graphql/base/action_event_page.rb +16 -0
- data/lib/ecoportal/api/graphql/base/activity.rb +38 -0
- data/lib/ecoportal/api/graphql/base/activity_log.rb +38 -0
- data/lib/ecoportal/api/graphql/base/ai_summary_version.rb +13 -8
- data/lib/ecoportal/api/graphql/base/auth_log.rb +24 -0
- data/lib/ecoportal/api/graphql/base/authorization_result.rb +20 -0
- data/lib/ecoportal/api/graphql/base/contractor_entity/member_changes.rb +17 -5
- data/lib/ecoportal/api/graphql/base/contractor_entity.rb +24 -24
- data/lib/ecoportal/api/graphql/base/date_time.rb +12 -12
- data/lib/ecoportal/api/graphql/base/delta_result.rb +16 -16
- data/lib/ecoportal/api/graphql/base/field.rb +12 -12
- data/lib/ecoportal/api/graphql/base/file_attachment.rb +15 -15
- data/lib/ecoportal/api/graphql/base/file_container.rb +12 -4
- data/lib/ecoportal/api/graphql/base/location_classification_type.rb +2 -0
- data/lib/ecoportal/api/graphql/base/location_node.rb +14 -14
- data/lib/ecoportal/api/graphql/base/location_structure/draft/structure.rb +37 -37
- data/lib/ecoportal/api/graphql/base/location_structure/draft.rb +93 -93
- data/lib/ecoportal/api/graphql/base/location_structure.rb +3 -0
- data/lib/ecoportal/api/graphql/base/minimal_dashboard.rb +25 -0
- data/lib/ecoportal/api/graphql/base/organization.rb +2 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/actions_list.rb +9 -9
- data/lib/ecoportal/api/graphql/base/page/data_field/ai_summary.rb +18 -18
- data/lib/ecoportal/api/graphql/base/page/data_field/checklist.rb +29 -29
- data/lib/ecoportal/api/graphql/base/page/data_field/contractor_entities.rb +26 -3
- data/lib/ecoportal/api/graphql/base/page/data_field/cross_reference.rb +1 -1
- data/lib/ecoportal/api/graphql/base/page/data_field/date_field.rb +23 -23
- data/lib/ecoportal/api/graphql/base/page/data_field/file_field.rb +47 -8
- data/lib/ecoportal/api/graphql/base/page/data_field/geo.rb +24 -24
- data/lib/ecoportal/api/graphql/base/page/data_field/image_gallery.rb +6 -3
- data/lib/ecoportal/api/graphql/base/page/data_field/law.rb +8 -8
- data/lib/ecoportal/api/graphql/base/page/data_field/mailbox.rb +9 -9
- data/lib/ecoportal/api/graphql/base/page/data_field/people.rb +50 -12
- data/lib/ecoportal/api/graphql/base/page/data_field/plain_text.rb +17 -17
- data/lib/ecoportal/api/graphql/base/page/data_field/rich_text.rb +26 -26
- data/lib/ecoportal/api/graphql/base/page/data_field/signature.rb +9 -9
- data/lib/ecoportal/api/graphql/base/page/data_field/smart_fill.rb +17 -17
- data/lib/ecoportal/api/graphql/base/page/data_field/table.rb +9 -9
- data/lib/ecoportal/api/graphql/base/page/data_field/tag_field.rb +21 -21
- data/lib/ecoportal/api/graphql/base/page/data_field.rb +12 -18
- data/lib/ecoportal/api/graphql/base/page/phased/stage.rb +51 -0
- data/lib/ecoportal/api/graphql/base/page/phased.rb +15 -15
- data/lib/ecoportal/api/graphql/base/page/section.rb +48 -48
- data/lib/ecoportal/api/graphql/base/page_info.rb +12 -12
- data/lib/ecoportal/api/graphql/base/pages_workflow/operation_interface.rb +39 -39
- data/lib/ecoportal/api/graphql/base/pages_workflow/operations/assign_to.rb +27 -27
- data/lib/ecoportal/api/graphql/base/pages_workflow/operations/send_notification.rb +30 -30
- data/lib/ecoportal/api/graphql/base/pages_workflow/recipient_config.rb +34 -34
- data/lib/ecoportal/api/graphql/base/pages_workflow.rb +35 -35
- data/lib/ecoportal/api/graphql/base/permissions.rb +15 -0
- data/lib/ecoportal/api/graphql/base/person_member.rb +22 -22
- data/lib/ecoportal/api/graphql/base/person_member_changelog.rb +23 -0
- data/lib/ecoportal/api/graphql/base/preset_view.rb +136 -1
- data/lib/ecoportal/api/graphql/base/preview_page.rb +23 -23
- data/lib/ecoportal/api/graphql/base/register.rb +6 -1
- data/lib/ecoportal/api/graphql/base/resource.rb +13 -13
- data/lib/ecoportal/api/graphql/base/template/change_log_entry.rb +118 -0
- data/lib/ecoportal/api/graphql/base/template.rb +2 -0
- data/lib/ecoportal/api/graphql/base.rb +9 -0
- data/lib/ecoportal/api/graphql/builder/action.rb +41 -41
- data/lib/ecoportal/api/graphql/builder/contractor_entity.rb +10 -0
- data/lib/ecoportal/api/graphql/builder/location_structure/draft.rb +64 -64
- data/lib/ecoportal/api/graphql/builder/location_structure.rb +40 -40
- data/lib/ecoportal/api/graphql/builder/page.rb +0 -16
- data/lib/ecoportal/api/graphql/builder/register/preset_view.rb +84 -84
- data/lib/ecoportal/api/graphql/builder/register.rb +49 -49
- data/lib/ecoportal/api/graphql/builder/template.rb +46 -0
- data/lib/ecoportal/api/graphql/builder/template_builder.rb +21 -2
- data/lib/ecoportal/api/graphql/compat/page_reference.rb +23 -23
- data/lib/ecoportal/api/graphql/compat/pages.rb +7 -2
- data/lib/ecoportal/api/graphql/compat/registers.rb +84 -84
- data/lib/ecoportal/api/graphql/compat/response.rb +14 -0
- data/lib/ecoportal/api/graphql/compat/search_results.rb +33 -33
- data/lib/ecoportal/api/graphql/compat.rb +17 -17
- data/lib/ecoportal/api/graphql/concerns/data_field_access.rb +71 -71
- data/lib/ecoportal/api/graphql/concerns/fragment_definitions.rb +68 -68
- data/lib/ecoportal/api/graphql/concerns/snake_camel_access.rb +60 -60
- data/lib/ecoportal/api/graphql/concerns/threadable.rb +58 -0
- data/lib/ecoportal/api/graphql/concerns.rb +1 -0
- data/lib/ecoportal/api/graphql/connection/action.rb +1 -1
- data/lib/ecoportal/api/graphql/connection/action_category.rb +1 -1
- data/lib/ecoportal/api/graphql/connection/activity.rb +11 -0
- data/lib/ecoportal/api/graphql/connection/activity_log.rb +11 -0
- data/lib/ecoportal/api/graphql/connection/auth_log.rb +11 -0
- data/lib/ecoportal/api/graphql/connection/contractor_entity.rb +1 -1
- data/lib/ecoportal/api/graphql/connection/minimal_dashboard.rb +11 -0
- data/lib/ecoportal/api/graphql/connection/page.rb +1 -1
- data/lib/ecoportal/api/graphql/connection/pages_workflow_command.rb +1 -1
- data/lib/ecoportal/api/graphql/connection/person_member.rb +1 -1
- data/lib/ecoportal/api/graphql/connection/person_member_changelog.rb +11 -0
- data/lib/ecoportal/api/graphql/connection/preset_view.rb +11 -11
- data/lib/ecoportal/api/graphql/connection/preview_page.rb +1 -1
- data/lib/ecoportal/api/graphql/connection/template_change_log.rb +19 -0
- data/lib/ecoportal/api/graphql/connection.rb +6 -0
- data/lib/ecoportal/api/graphql/diff/change.rb +7 -2
- data/lib/ecoportal/api/graphql/diff/command_synthesizer.rb +19 -1
- data/lib/ecoportal/api/graphql/diff/pairing/signals.rb +21 -1
- data/lib/ecoportal/api/graphql/diff/version_diff.rb +13 -6
- data/lib/ecoportal/api/graphql/error/locations_error/fetch_nested.rb +51 -51
- data/lib/ecoportal/api/graphql/error/locations_error.rb +28 -28
- data/lib/ecoportal/api/graphql/error/locations_validation_error.rb +20 -20
- data/lib/ecoportal/api/graphql/error/validation_errors.rb +28 -28
- data/lib/ecoportal/api/graphql/error.rb +12 -12
- data/lib/ecoportal/api/graphql/file_upload/client.rb +199 -140
- data/lib/ecoportal/api/graphql/file_upload.rb +10 -10
- data/lib/ecoportal/api/graphql/fragment/action.rb +65 -65
- data/lib/ecoportal/api/graphql/fragment/action_category.rb +17 -17
- data/lib/ecoportal/api/graphql/fragment/activity.rb +84 -0
- data/lib/ecoportal/api/graphql/fragment/activity_log.rb +75 -0
- data/lib/ecoportal/api/graphql/fragment/auth_log.rb +29 -0
- data/lib/ecoportal/api/graphql/fragment/authorization_result.rb +14 -0
- data/lib/ecoportal/api/graphql/fragment/contractor_entity.rb +20 -20
- data/lib/ecoportal/api/graphql/fragment/location_node.rb +1 -0
- data/lib/ecoportal/api/graphql/fragment/locations_error.rb +19 -19
- data/lib/ecoportal/api/graphql/fragment/minimal_dashboard.rb +31 -0
- data/lib/ecoportal/api/graphql/fragment/page.rb +1 -0
- data/lib/ecoportal/api/graphql/fragment/pages/common_page_union.rb +23 -0
- data/lib/ecoportal/api/graphql/fragment/pages.rb +15 -15
- data/lib/ecoportal/api/graphql/fragment/pagination.rb +17 -17
- data/lib/ecoportal/api/graphql/fragment/permissions.rb +98 -0
- data/lib/ecoportal/api/graphql/fragment/person_member_changelog.rb +33 -0
- data/lib/ecoportal/api/graphql/fragment/template_change_log.rb +102 -0
- data/lib/ecoportal/api/graphql/fragment.rb +8 -0
- data/lib/ecoportal/api/graphql/helpers/locations_tree.rb +41 -41
- data/lib/ecoportal/api/graphql/helpers.rb +10 -10
- data/lib/ecoportal/api/graphql/input/action/archive.rb +14 -14
- data/lib/ecoportal/api/graphql/input/action/create.rb +13 -13
- data/lib/ecoportal/api/graphql/input/action/update.rb +12 -0
- data/lib/ecoportal/api/graphql/input/action.rb +14 -14
- data/lib/ecoportal/api/graphql/input/contractor_entity/create.rb +14 -14
- data/lib/ecoportal/api/graphql/input/contractor_entity/destroy.rb +13 -13
- data/lib/ecoportal/api/graphql/input/contractor_entity/manager_settings.rb +20 -0
- data/lib/ecoportal/api/graphql/input/contractor_entity/update.rb +6 -27
- data/lib/ecoportal/api/graphql/input/contractor_entity.rb +1 -0
- data/lib/ecoportal/api/graphql/input/date_range.rb +16 -0
- data/lib/ecoportal/api/graphql/input/delta_input.rb +16 -16
- data/lib/ecoportal/api/graphql/input/id_diff.rb +11 -11
- data/lib/ecoportal/api/graphql/input/location_structure/apply_commands.rb +2 -2
- data/lib/ecoportal/api/graphql/input/location_structure/archive_command.rb +13 -13
- data/lib/ecoportal/api/graphql/input/location_structure/delete_command.rb +13 -13
- data/lib/ecoportal/api/graphql/input/location_structure/draft/add_commands.rb +2 -2
- data/lib/ecoportal/api/graphql/input/location_structure/draft/create.rb +15 -15
- data/lib/ecoportal/api/graphql/input/location_structure/draft/delete.rb +15 -15
- data/lib/ecoportal/api/graphql/input/location_structure/draft/drop_bad_commands.rb +16 -16
- data/lib/ecoportal/api/graphql/input/location_structure/draft/publish.rb +16 -16
- data/lib/ecoportal/api/graphql/input/location_structure/draft.rb +19 -19
- data/lib/ecoportal/api/graphql/input/location_structure/insert_command.rb +21 -13
- data/lib/ecoportal/api/graphql/input/location_structure/move_command.rb +14 -14
- data/lib/ecoportal/api/graphql/input/location_structure/reorder_command.rb +13 -13
- data/lib/ecoportal/api/graphql/input/location_structure/unarchive_command.rb +13 -13
- data/lib/ecoportal/api/graphql/input/location_structure/update_command.rb +6 -2
- data/lib/ecoportal/api/graphql/input/location_structure.rb +20 -20
- data/lib/ecoportal/api/graphql/input/page/archive.rb +14 -14
- data/lib/ecoportal/api/graphql/input/page/build_from_template.rb +13 -13
- data/lib/ecoportal/api/graphql/input/page/create_draft.rb +13 -13
- data/lib/ecoportal/api/graphql/input/page/create_from_template.rb +18 -18
- data/lib/ecoportal/api/graphql/input/page/delete_draft.rb +13 -13
- data/lib/ecoportal/api/graphql/input/page/publish_draft.rb +13 -13
- data/lib/ecoportal/api/graphql/input/page/review_task.rb +27 -14
- data/lib/ecoportal/api/graphql/input/page/unarchive.rb +14 -14
- data/lib/ecoportal/api/graphql/input/page.rb +26 -26
- data/lib/ecoportal/api/graphql/input/preset_view/create.rb +18 -18
- data/lib/ecoportal/api/graphql/input/preset_view/permission.rb +16 -16
- data/lib/ecoportal/api/graphql/input/preset_view/update.rb +17 -2
- data/lib/ecoportal/api/graphql/input/preset_view.rb +14 -14
- data/lib/ecoportal/api/graphql/input/register/create.rb +18 -18
- data/lib/ecoportal/api/graphql/input/register/update.rb +15 -15
- data/lib/ecoportal/api/graphql/input/register.rb +13 -13
- data/lib/ecoportal/api/graphql/input/search.rb +13 -13
- data/lib/ecoportal/api/graphql/input/search_conf/ai_generator.rb +234 -234
- data/lib/ecoportal/api/graphql/input/search_filter.rb +12 -12
- data/lib/ecoportal/api/graphql/input/search_sorter.rb +11 -11
- data/lib/ecoportal/api/graphql/input/workflow_command/add_action_tag.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/add_binding.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/add_checklist_field_item.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_comment_tagging_user_group.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/add_default_direct_strategy_user.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/add_default_strategy.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/add_direct_strategy_user.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/add_field.rb +10 -9
- data/lib/ecoportal/api/graphql/input/workflow_command/add_force.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/add_linked_field_config.rb +23 -23
- data/lib/ecoportal/api/graphql/input/workflow_command/add_linked_helper.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/add_operation.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/add_operation_direct_strategy_user.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/add_operation_strategy.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_action_type.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_filter.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_people_field.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_task_config.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_user.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/add_scheduled_callback.rb +23 -23
- data/lib/ecoportal/api/graphql/input/workflow_command/add_scheduled_callback_action.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/add_section.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/add_select_field_option.rb +25 -19
- data/lib/ecoportal/api/graphql/input/workflow_command/add_smart_fill_config.rb +23 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_stage.rb +3 -2
- data/lib/ecoportal/api/graphql/input/workflow_command/add_stage_section.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/add_stage_tag.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/add_strategy.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/add_task.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/add_task_assignment_user_group.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/add_viewable_field.rb +45 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_workflow_callback.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/archive_public_config.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/collapse_section.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/create_public_config.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_binding.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_checklist_field_item.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_creator_permissions.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_default_strategy.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_field_configuration.rb +17 -2
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_force.rb +21 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_gauge_field_stop.rb +19 -19
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_linked_field_config.rb +19 -19
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_linked_helper.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_operation.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_operation_strategy.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_public_config.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_reminder.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_required_sign_offs.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_restrict_comment_tagging.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_restrict_task_assignment.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_scheduled_callback.rb +22 -22
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_section_header.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_select_field_option.rb +23 -19
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_smart_fill_config.rb +21 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_stage.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_strategy.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_task_due.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_template_advanced_settings.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_template_basic_settings.rb +32 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_template_container_uid.rb +45 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/{edit_page_creator_permissions.rb → edit_template_creator_permissions.rb} +3 -2
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_template_descriptions.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_trigger.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/expand_section.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/action_list.rb +31 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/contractor_entities.rb +28 -24
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/cross_reference.rb +9 -1
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/date.rb +15 -2
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/file.rb +21 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/gauge.rb +20 -20
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/image_gallery.rb +3 -2
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/location_field.rb +24 -24
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/people.rb +27 -3
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/plain_text.rb +9 -2
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/rich_text.rb +3 -2
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/select.rb +3 -2
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/signature.rb +20 -20
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/table.rb +25 -25
- data/lib/ecoportal/api/graphql/input/workflow_command/manage_copy_page_configuration.rb +47 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/move_field.rb +3 -2
- data/lib/ecoportal/api/graphql/input/workflow_command/move_stage.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/move_viewable_field.rb +33 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_action_tag.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_binding.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_callback.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_checklist_field_item.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_comment_tagging_user_group.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_default_direct_strategy_user.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_default_strategy.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_direct_strategy_user.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_field.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_force.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_linked_helper.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_operation.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_operation_direct_strategy_user.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_operation_strategy.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_action_type.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_filter.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_people_field.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_task_config.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_user.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_scheduled_callback.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_section.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_smart_fill_config.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_stage.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_stage_section.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_stage_tag.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_strategy.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_task.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_task_assignment_user_group.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_task_due.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_task_priority_level.rb +18 -18
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_viewable_field.rb +21 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/reorder_forces.rb +3 -2
- data/lib/ecoportal/api/graphql/input/workflow_command/reorder_section.rb +3 -2
- data/lib/ecoportal/api/graphql/input/workflow_command.rb +46 -5
- data/lib/ecoportal/api/graphql/input.rb +1 -0
- data/lib/ecoportal/api/graphql/interface/base_page.rb +50 -3
- data/lib/ecoportal/api/graphql/interface/location_structure/command.rb +2 -1
- data/lib/ecoportal/api/graphql/interface/location_structure/node.rb +43 -43
- data/lib/ecoportal/api/graphql/interface/location_structure.rb +14 -14
- data/lib/ecoportal/api/graphql/interface.rb +11 -11
- data/lib/ecoportal/api/graphql/logic/base_model.rb +15 -15
- data/lib/ecoportal/api/graphql/logic/base_query.rb +260 -193
- data/lib/ecoportal/api/graphql/logic/connection.rb +17 -0
- data/lib/ecoportal/api/graphql/logic/input.rb +127 -0
- data/lib/ecoportal/api/graphql/logic/mutation.rb +59 -59
- data/lib/ecoportal/api/graphql/logic/payload.rb +42 -42
- data/lib/ecoportal/api/graphql/logic/query.rb +23 -23
- data/lib/ecoportal/api/graphql/logic/query_array.rb +30 -30
- data/lib/ecoportal/api/graphql/logic/query_connection.rb +48 -48
- data/lib/ecoportal/api/graphql/logic.rb +18 -18
- data/lib/ecoportal/api/graphql/model/account.rb +15 -15
- data/lib/ecoportal/api/graphql/model/action.rb +22 -22
- data/lib/ecoportal/api/graphql/model/action_event.rb +14 -0
- data/lib/ecoportal/api/graphql/model/action_event_page.rb +10 -0
- data/lib/ecoportal/api/graphql/model/activity.rb +14 -0
- data/lib/ecoportal/api/graphql/model/activity_log.rb +31 -0
- data/lib/ecoportal/api/graphql/model/ai_summary_version.rb +10 -10
- data/lib/ecoportal/api/graphql/model/auth_log.rb +11 -0
- data/lib/ecoportal/api/graphql/model/authorization_result.rb +12 -0
- data/lib/ecoportal/api/graphql/model/contractor_entity.rb +12 -12
- data/lib/ecoportal/api/graphql/model/field.rb +10 -10
- data/lib/ecoportal/api/graphql/model/file_attachment.rb +10 -10
- data/lib/ecoportal/api/graphql/model/file_container.rb +11 -11
- data/lib/ecoportal/api/graphql/model/location_node.rb +14 -14
- data/lib/ecoportal/api/graphql/model/location_structure/draft/structure.rb +15 -15
- data/lib/ecoportal/api/graphql/model/location_structure/draft.rb +15 -15
- data/lib/ecoportal/api/graphql/model/location_structure.rb +16 -16
- data/lib/ecoportal/api/graphql/model/minimal_dashboard.rb +14 -0
- data/lib/ecoportal/api/graphql/model/organization.rb +36 -0
- data/lib/ecoportal/api/graphql/model/page/basic.rb +14 -14
- data/lib/ecoportal/api/graphql/model/page/data_field.rb +12 -12
- data/lib/ecoportal/api/graphql/model/page/phased/stage.rb +14 -14
- data/lib/ecoportal/api/graphql/model/page/phased.rb +17 -0
- data/lib/ecoportal/api/graphql/model/page/section.rb +12 -12
- data/lib/ecoportal/api/graphql/model/page_union.rb +21 -21
- data/lib/ecoportal/api/graphql/model/pages_workflow.rb +20 -20
- data/lib/ecoportal/api/graphql/model/permissions.rb +179 -0
- data/lib/ecoportal/api/graphql/model/person_member.rb +7 -0
- data/lib/ecoportal/api/graphql/model/person_member_changelog.rb +15 -0
- data/lib/ecoportal/api/graphql/model/preset_view.rb +10 -10
- data/lib/ecoportal/api/graphql/model/preview_page.rb +10 -10
- data/lib/ecoportal/api/graphql/model/register.rb +10 -10
- data/lib/ecoportal/api/graphql/model/resource.rb +13 -13
- data/lib/ecoportal/api/graphql/model/template/change_log_entry.rb +19 -0
- data/lib/ecoportal/api/graphql/model/template.rb +4 -1
- data/lib/ecoportal/api/graphql/model/user.rb +14 -14
- data/lib/ecoportal/api/graphql/model.rb +9 -0
- data/lib/ecoportal/api/graphql/mutation/action/archive.rb +41 -41
- data/lib/ecoportal/api/graphql/mutation/action/create.rb +40 -40
- data/lib/ecoportal/api/graphql/mutation/action/update.rb +40 -40
- data/lib/ecoportal/api/graphql/mutation/action.rb +14 -14
- data/lib/ecoportal/api/graphql/mutation/ai_summary/generate.rb +21 -11
- data/lib/ecoportal/api/graphql/mutation/ai_summary/submit_feedback.rb +26 -11
- data/lib/ecoportal/api/graphql/mutation/ai_summary.rb +13 -13
- data/lib/ecoportal/api/graphql/mutation/contractor_entity/create.rb +40 -40
- data/lib/ecoportal/api/graphql/mutation/contractor_entity/destroy.rb +40 -40
- data/lib/ecoportal/api/graphql/mutation/contractor_entity/update.rb +40 -40
- data/lib/ecoportal/api/graphql/mutation/contractor_entity/update_manager_settings.rb +37 -0
- data/lib/ecoportal/api/graphql/mutation/contractor_entity.rb +1 -0
- data/lib/ecoportal/api/graphql/mutation/file_container/upload.rb +78 -0
- data/lib/ecoportal/api/graphql/mutation/file_container.rb +15 -0
- data/lib/ecoportal/api/graphql/mutation/location_structure/apply_commands.rb +54 -54
- data/lib/ecoportal/api/graphql/mutation/location_structure/draft/add_commands.rb +55 -55
- data/lib/ecoportal/api/graphql/mutation/location_structure/draft/create.rb +54 -54
- data/lib/ecoportal/api/graphql/mutation/location_structure/draft/delete.rb +43 -43
- data/lib/ecoportal/api/graphql/mutation/location_structure/draft/drop_bad_commands.rb +56 -56
- data/lib/ecoportal/api/graphql/mutation/location_structure/draft/publish.rb +66 -66
- data/lib/ecoportal/api/graphql/mutation/location_structure/draft.rb +18 -18
- data/lib/ecoportal/api/graphql/mutation/location_structure.rb +13 -13
- data/lib/ecoportal/api/graphql/mutation/page/approve_review_task.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/page/archive.rb +40 -40
- data/lib/ecoportal/api/graphql/mutation/page/batch_update_review_task.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/page/build_from_template.rb +50 -50
- data/lib/ecoportal/api/graphql/mutation/page/create_draft.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/page/create_from_template.rb +43 -43
- data/lib/ecoportal/api/graphql/mutation/page/delete_draft.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/page/publish_draft.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/page/reject_review_task.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/page/restart_review_task.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/page/unarchive.rb +40 -40
- data/lib/ecoportal/api/graphql/mutation/page/undo_review_task.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/page/update.rb +40 -40
- data/lib/ecoportal/api/graphql/mutation/page.rb +28 -28
- data/lib/ecoportal/api/graphql/mutation/preset_view/create.rb +35 -35
- data/lib/ecoportal/api/graphql/mutation/preset_view/destroy.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/preset_view/permission.rb +37 -37
- data/lib/ecoportal/api/graphql/mutation/preset_view/update.rb +35 -35
- data/lib/ecoportal/api/graphql/mutation/preset_view.rb +15 -15
- data/lib/ecoportal/api/graphql/mutation/register/create.rb +35 -35
- data/lib/ecoportal/api/graphql/mutation/register/destroy.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/register/update.rb +35 -35
- data/lib/ecoportal/api/graphql/mutation/register.rb +14 -14
- data/lib/ecoportal/api/graphql/mutation/template/update_related_page.rb +79 -0
- data/lib/ecoportal/api/graphql/mutation/template.rb +1 -0
- data/lib/ecoportal/api/graphql/mutation.rb +1 -1
- data/lib/ecoportal/api/graphql/payload/action/archive.rb +13 -13
- data/lib/ecoportal/api/graphql/payload/action/create.rb +13 -13
- data/lib/ecoportal/api/graphql/payload/action/update.rb +13 -13
- data/lib/ecoportal/api/graphql/payload/action.rb +14 -14
- data/lib/ecoportal/api/graphql/payload/ai_summary_generate.rb +12 -12
- data/lib/ecoportal/api/graphql/payload/contractor_entity/create.rb +13 -13
- data/lib/ecoportal/api/graphql/payload/contractor_entity/destroy.rb +12 -12
- data/lib/ecoportal/api/graphql/payload/contractor_entity/manager_settings.rb +20 -0
- data/lib/ecoportal/api/graphql/payload/contractor_entity/update.rb +12 -12
- data/lib/ecoportal/api/graphql/payload/contractor_entity.rb +1 -0
- data/lib/ecoportal/api/graphql/payload/kickstand/bulk_update_jobs.rb +2 -2
- data/lib/ecoportal/api/graphql/payload/kickstand/bulk_update_workflows.rb +2 -2
- data/lib/ecoportal/api/graphql/payload/location_structure/apply_commands.rb +51 -51
- data/lib/ecoportal/api/graphql/payload/location_structure/command_execution_result.rb +50 -50
- data/lib/ecoportal/api/graphql/payload/location_structure/draft/add_commands.rb +30 -30
- data/lib/ecoportal/api/graphql/payload/location_structure/draft/delete.rb +30 -30
- data/lib/ecoportal/api/graphql/payload/location_structure/draft/drop_bad_commands.rb +43 -43
- data/lib/ecoportal/api/graphql/payload/location_structure/draft/publish.rb +63 -63
- data/lib/ecoportal/api/graphql/payload/location_structure/draft.rb +18 -18
- data/lib/ecoportal/api/graphql/payload/location_structure.rb +14 -14
- data/lib/ecoportal/api/graphql/payload/ok_payload.rb +1 -1
- data/lib/ecoportal/api/graphql/payload/page/archive.rb +13 -13
- data/lib/ecoportal/api/graphql/payload/page/build_from_template.rb +13 -13
- data/lib/ecoportal/api/graphql/payload/page/create_from_template.rb +13 -13
- data/lib/ecoportal/api/graphql/payload/page/draft.rb +1 -1
- data/lib/ecoportal/api/graphql/payload/page/review_task.rb +1 -1
- data/lib/ecoportal/api/graphql/payload/page/unarchive.rb +13 -13
- data/lib/ecoportal/api/graphql/payload/page/update.rb +13 -13
- data/lib/ecoportal/api/graphql/payload/preset_view.rb +1 -1
- data/lib/ecoportal/api/graphql/payload/register.rb +1 -1
- data/lib/ecoportal/api/graphql/payload/template/update_related_page.rb +15 -0
- data/lib/ecoportal/api/graphql/payload/template.rb +1 -0
- data/lib/ecoportal/api/graphql/payload/upload.rb +12 -0
- data/lib/ecoportal/api/graphql/payload.rb +1 -0
- data/lib/ecoportal/api/graphql/query/action.rb +33 -33
- data/lib/ecoportal/api/graphql/query/action_categories.rb +53 -53
- data/lib/ecoportal/api/graphql/query/actions.rb +43 -43
- data/lib/ecoportal/api/graphql/query/activity_logs.rb +78 -0
- data/lib/ecoportal/api/graphql/query/auth_logs.rb +51 -0
- data/lib/ecoportal/api/graphql/query/contractor_entities.rb +53 -53
- data/lib/ecoportal/api/graphql/query/dashboard_search.rb +57 -0
- data/lib/ecoportal/api/graphql/query/file_upload_signature.rb +76 -76
- data/lib/ecoportal/api/graphql/query/location_classifications.rb +39 -39
- data/lib/ecoportal/api/graphql/query/location_structure.rb +2 -0
- data/lib/ecoportal/api/graphql/query/location_structures.rb +2 -0
- data/lib/ecoportal/api/graphql/query/page.rb +6 -1
- data/lib/ecoportal/api/graphql/query/page_activities.rb +56 -0
- data/lib/ecoportal/api/graphql/query/page_delta.rb +47 -47
- data/lib/ecoportal/api/graphql/query/pages.rb +59 -59
- data/lib/ecoportal/api/graphql/query/permissions.rb +35 -0
- data/lib/ecoportal/api/graphql/query/person_member_changelogs.rb +53 -0
- data/lib/ecoportal/api/graphql/query/person_members.rb +76 -0
- data/lib/ecoportal/api/graphql/query/register_preset_views.rb +1 -1
- data/lib/ecoportal/api/graphql/query/register_preview_pages.rb +83 -83
- data/lib/ecoportal/api/graphql/query/template_change_log.rb +118 -0
- data/lib/ecoportal/api/graphql/query/templates.rb +53 -53
- data/lib/ecoportal/api/graphql/query.rb +8 -0
- data/lib/ecoportal/api/graphql_version.rb +1 -1
- data/lib/ecoportal/api-graphql.rb +10 -10
- metadata +82 -19
- data/lib/ecoportal/api/common/graphql/CLAUDE.md +0 -36
- data/lib/ecoportal/api/common/graphql/model/CLAUDE.md +0 -28
- data/lib/ecoportal/api/graphql/CLAUDE.md +0 -37
- data/lib/ecoportal/api/graphql/base/CLAUDE.md +0 -50
- data/lib/ecoportal/api/graphql/builder/CLAUDE.md +0 -65
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_page.rb +0 -28
- data/lib/ecoportal/api/graphql/mutation/smart_fill/generate.rb +0 -36
- data/lib/ecoportal/api/graphql/mutation/smart_fill/submit_feedback.rb +0 -40
- data/lib/ecoportal/api/graphql/mutation/smart_fill.rb +0 -13
data/CHANGELOG.md
CHANGED
|
@@ -2,15 +2,755 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
-
## [
|
|
5
|
+
## [2.2.0] - 2026-09-02
|
|
6
|
+
|
|
7
|
+
★ **This release supersedes 2.1.0, which was version-bumped and changelogged on 2026-08-21 but never
|
|
8
|
+
tagged or published** — RubyGems' highest was still 2.0.0. Do not go looking for 2.1.0; it does not
|
|
9
|
+
exist as a gem. Its contents are included below by inheritance (they were already on `main`), and
|
|
10
|
+
2.2.0 adds what landed after that bump. Publishing the 2.1.0 artifact would have shipped a state
|
|
11
|
+
already superseded by merged `lib/` fixes and required a second release immediately.
|
|
12
|
+
|
|
13
|
+
**Minor, not patch:** `Input::WorkflowCommand::AddSelectFieldOption.build` now REQUIRES a `value:`
|
|
14
|
+
keyword. Under the versioning convention (minor = breaking, patch = compatible) that is breaking,
|
|
15
|
+
even though the omitted argument meant the old call shape was already rejected by the server — a
|
|
16
|
+
caller adapting to this is changing working-looking code.
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- `tools/template_yaml/yaml_to_raw_json.py` -- a small, self-contained YAML-to-raw-JSON bridge
|
|
21
|
+
(inlines the BSON-aware `EpLoader`/`load_dump` the retired Python projector used) so a template
|
|
22
|
+
backup YAML attached to a ticket can still be fed to the Ruby CLI, which only ever reads JSON.
|
|
23
|
+
Drops `update_histories` by default (churn neither projector read, and a recurring source of
|
|
24
|
+
corrupted ObjectIds), with `--keep-churn` to keep it.
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
- **`Page#all_tags` / `Stage#all_tags` read side** (`Model::Page::Phased`, `Base::Page::Phased::Stage`,
|
|
28
|
+
`Interface::BasePage`): the compiled tag set for a page or a single stage, folded client-side from
|
|
29
|
+
the page's `baseTags` and the stage's own tags, with both fetched by the page fragments
|
|
30
|
+
(`Fragment::Page`, `Fragment::Pages::CommonPageUnion`). `Stage#page` now resolves through the
|
|
31
|
+
native `DoubleModel` root reference rather than a hand-rolled back-pointer, and `location_ids`
|
|
32
|
+
is redirected page -> stage accordingly.
|
|
33
|
+
|
|
34
|
+
★ This code was written on 2026-07-06 and then sat on three unmerged local branches for seven
|
|
35
|
+
weeks. `main` never received it in any form, and no other trace of it exists in history --
|
|
36
|
+
deleting those branches during a sweep would have lost a spec-covered feature permanently. It is
|
|
37
|
+
cherry-picked here onto current `main` rather than merged from the branch: `main` has since
|
|
38
|
+
changed four of the five files involved, so taking the branch's copies wholesale would have
|
|
39
|
+
reverted shipped fixes. That is the stranded-work failure mode this repo has a root-cause note
|
|
40
|
+
about, caught this time only because a branch sweep asked what each unmerged branch actually
|
|
41
|
+
contained.
|
|
42
|
+
|
|
43
|
+
- `tools/template_yaml/forces_walker.rb`: Ruby port of the template projector's `project_forces` /
|
|
44
|
+
`script_identifiers` (P4), classifying each binding as a FIELD or a SECTION target rather than
|
|
45
|
+
conflating the two, and reporting the unread force-level `globalBindings` gap as unverified
|
|
46
|
+
instead of as a finding. Gated by `tools/template_yaml/compare_forces.rb` against the Python IR.
|
|
47
|
+
|
|
48
|
+
- `tools/template_yaml/review.rb` / `update_gate.rb`: Ruby port of the template projector's
|
|
49
|
+
`review` / `update_gate` (P5), refusing a template's bulk update PER TEMPLATE (not per field)
|
|
50
|
+
when no field carries a usable identifier or identifiers are non-unique. Adds a Ruby-only
|
|
51
|
+
`ximport` tooltip guard: fields marked exclude-from-import are counted and protected, never
|
|
52
|
+
treated as overwritable. `Delta.call`'s `reviewer:` seam is now wired to `Review.method(:call)`,
|
|
53
|
+
so `review_findings` appears in the delta payload. Gated by `tools/template_yaml/compare_gate.rb`
|
|
54
|
+
against the 18 M&S templates -- refusal set matches the Python exactly.
|
|
55
|
+
|
|
56
|
+
- `tools/template_yaml/model.rb`: Ruby port of the template projector's `project(doc, source)`
|
|
57
|
+
(P3's IR assembly), composing field and force walks into a compact IR dict with key order
|
|
58
|
+
matching the Python prototype for P8 differential acceptance.
|
|
59
|
+
- `tools/template_yaml/render_markdown.rb`: Ruby port of `render_markdown(model, findings)` (P7),
|
|
60
|
+
rendering a template and its review findings as Markdown with all Python quirks reproduced
|
|
61
|
+
verbatim: the dead `stage` column, escape-then-truncate on `label`, redundant `type` re-split,
|
|
62
|
+
CRLF-to-LF normalization on force scripts, and preserved literals like `'(unnamed)'`,
|
|
63
|
+
`'(no custom script)'`, `'(none)'`.
|
|
64
|
+
- `tools/template_yaml/cli.rb`: Ruby CLI entrypoint matching Python's `main()` (P7), supporting
|
|
65
|
+
single-file and directory modes, `--out`, `--json`, and `--delta` flags. **Input is JSON
|
|
66
|
+
(`*.json`), not YAML**, per Loader's design (see loader.rb header). File writes are LF-only
|
|
67
|
+
on all platforms via binary mode. Directory mode processes `*.json` files alphabetically,
|
|
68
|
+
accumulates an `_index.md` at the end, and leaves earlier files on disk if an error occurs
|
|
69
|
+
mid-run (no transactional cleanup).
|
|
70
|
+
|
|
71
|
+
- `tools/template_yaml/differential_gate.rb`: P8, the template-yaml Ruby port's acceptance gate.
|
|
72
|
+
Regenerates BOTH IRs fresh in one run -- Ruby in-process (`Loader` -> `Model.build` -> `Review`
|
|
73
|
+
-> `UpdateGate`) over the `*.json` corpus, Python via a single batched subprocess (direct
|
|
74
|
+
import of `ep_template_yaml.py`, not its CLI) over the `*.yaml` corpus -- and diffs the ENTIRE
|
|
75
|
+
IR: every template attribute, every field, every force (incl. bindings), every review finding,
|
|
76
|
+
and the `update_gate` refusal set. Live run over the 18 M&S templates: **`P8 GATE: PASS`**,
|
|
77
|
+
0 unexpected divergences, 12 expected (the six known-corrected ObjectIds, each seen twice --
|
|
78
|
+
once as a field id, once as a binding `reference_id`).
|
|
79
|
+
- `tools/template_yaml/known_divergences.rb`: the six-id whitelist and its `corrupted_id?` rule,
|
|
80
|
+
extracted out of `compare_fields.rb` so P3's gate and the new P8 gate share one definition
|
|
81
|
+
instead of two copies drifting apart.
|
|
82
|
+
- Fixed a Ruby port defect in `review.rb`, found live by the P8 differential run: finding
|
|
83
|
+
`detail` text quoted force/binding/field names with Ruby's `String#inspect` (always
|
|
84
|
+
double-quoted) where the Python source uses `%r` (CPython `repr()`, single-quoted by
|
|
85
|
+
default). Added `Review.py_repr` to reproduce Python's exact quoting.
|
|
86
|
+
- Excluded `patch_ver` and `updated_at` from P8's template-attribute comparison, alongside the
|
|
87
|
+
pre-existing `source_file` exclusion: the `templates_yaml`/`templates_json` fixture corpora
|
|
88
|
+
under `tmp/mns_01_tooltip_update/` are two separate exports pulled two days apart (confirmed
|
|
89
|
+
by file mtime), so these two pass-through fields legitimately disagree -- a corpus-provenance
|
|
90
|
+
artifact, not a port defect. `compare_fields.rb` / `compare_forces.rb`'s existing 0-unexpected
|
|
91
|
+
results already proved field/force content is identical across the two pulls.
|
|
92
|
+
|
|
93
|
+
### Changed
|
|
94
|
+
|
|
95
|
+
- **Changed** what a failing query prints. `Logic::BaseQuery`'s rescue used to `pp kargs` /
|
|
96
|
+
`pp query_params` / `pp block` to **stdout** on every error. That existed for a real reason —
|
|
97
|
+
graphlient masks the origin, so it was the only way to see which query failed — but it put GraphQL
|
|
98
|
+
variables (page ids, emails, field values) on stdout and into CI logs. Ruby populates `.cause` when
|
|
99
|
+
raising inside a rescue, so the original error keeps the source location `graphql-client`
|
|
100
|
+
deliberately sets: the report now names `err.cause`'s class and **the failing query's own source
|
|
101
|
+
location** on **stderr**, which is more of what the dump was for. Variables are emitted only when
|
|
102
|
+
the client's existing `deep_logging` flag is on; `pp block` is dropped. A blank message (which
|
|
103
|
+
graphlient's `GraphQLError#to_s` can render) is now labelled instead of printing nothing.
|
|
104
|
+
Tracked as Q-43.
|
|
105
|
+
|
|
106
|
+
### Fixed
|
|
107
|
+
|
|
108
|
+
- **Fixed** `currentOrganization.pageActivities` returning nothing. The wiring in
|
|
109
|
+
`Model::Organization` injected `base_path: ['currentOrganization']`, which overrides the
|
|
110
|
+
`base_path 'currentOrganization.page'` declared by `Query::PageActivities` — so the client
|
|
111
|
+
dug `currentOrganization.activities`, a path the emitted document never contains (the
|
|
112
|
+
inline-fragment `activities` merges into `page`). Added `subpath: 'page'`, plus a spec that
|
|
113
|
+
compares every wired query's declared base_path against the one the wiring injects, so the
|
|
114
|
+
whole class of bug is guarded rather than the one instance. Tracked as Q-13.
|
|
115
|
+
|
|
116
|
+
- **Fixed** `Common::GraphQL::ResponseError` discarding `errors[].extensions`. It now carries the
|
|
117
|
+
raw error entries and exposes `#errors`, `#extensions`, `#codes`, `#details`, `#full_messages`
|
|
118
|
+
and `#unauthorized?`. This is what makes a permission problem distinguishable from a request
|
|
119
|
+
problem in Ruby — the diagnosis the M&S pack tells customers to perform, which until now no tool
|
|
120
|
+
built on this gem could actually follow. The message still LEADS with the joined server messages
|
|
121
|
+
(existing matchers keep working) and appends `code:` / `details:` after them. `tools/mns/cli.rb`
|
|
122
|
+
now reports the server's own classification instead of sniffing the message for `/unauthoriz/i` —
|
|
123
|
+
a sniff that could not tell a policy refusal from a FIELD-level gate. Tracked as Q-27.
|
|
124
|
+
|
|
125
|
+
- **Fixed** `Payload::Kickstand::BulkUpdateJobs` and `BulkUpdateWorkflows` raising `NoMethodError`
|
|
126
|
+
on `#items` and `#errors`. Both called `from_doc`, which is a per-class convention in this gem
|
|
127
|
+
(only 7 classes define one) and does not exist on `Base::Kickstand::Job`/`Workflow` or on
|
|
128
|
+
`Error::ValidationErrors`. Any caller reading the result of a Kickstand bulk update crashed.
|
|
129
|
+
Replaced with the real constructor, `new(doc)`. These two classes had **no spec of any kind** —
|
|
130
|
+
that is why it shipped — so this adds the missing coverage (12 examples over both, shared) as
|
|
131
|
+
well as the guard. Found while mapping the client's failure surface for Q-31.
|
|
132
|
+
|
|
133
|
+
- **Packaging allowlist is now keyed on the full path, not the root directory.** `spec.files`
|
|
134
|
+
previously allowed anything under `lib/` or `exe/`, which packaged five `CLAUDE.md`
|
|
135
|
+
agent-instruction files living inside `lib/` (573 files now ship, down from 578). The
|
|
136
|
+
publish-time gate in `scripts/release_smoke_check.rb` had the same hole -- it exempted `lib/`
|
|
137
|
+
wholesale, so it could not see them by construction. Both now require every packaged path to
|
|
138
|
+
match `lib/**/*.rb`, `exe/*`, or one of the three named root docs, and the rule is pinned by
|
|
139
|
+
`spec/packaging_spec.rb` (15 examples, including one that proves the excluded files remain
|
|
140
|
+
tracked in the repo). No credentials or customer data were ever affected.
|
|
141
|
+
|
|
142
|
+
- **Seven workflow-command input builders were silently discarding arguments the backend accepts.**
|
|
143
|
+
Each builder filters its keyword arguments through an allowlist with `kwargs.slice(*KEYS)`, so a
|
|
144
|
+
key missing from the allowlist is dropped before the request is built: no error, no warning, no
|
|
145
|
+
effect. The mutation succeeds and does nothing.
|
|
146
|
+
|
|
147
|
+
| command | argument restored |
|
|
148
|
+
|---|---|
|
|
149
|
+
| `addSelectFieldOption` | `value` — ★ `required: true` on the backend, so **every call this builder produced was rejected by the server** |
|
|
150
|
+
| `editSelectFieldOption` | `value` |
|
|
151
|
+
| `editFieldConfiguration` | `required`, `hiddenOnReports` |
|
|
152
|
+
| `editTemplateBasicSettings` | `enableCopyPage` |
|
|
153
|
+
| `EditFieldConfiguration::PlainText` | `multiline` |
|
|
154
|
+
| `EditFieldConfiguration::ContractorEntities` | `applyPermissionsToParent` (distinct from `applyAttachedContractorsPermissionsTo`, which was already present) |
|
|
155
|
+
| `editForce` | `lastSyncedAt` |
|
|
156
|
+
|
|
157
|
+
Found by comparing all 123 command-bus inputs against the backend Rails source rather than
|
|
158
|
+
against the gem's stored introspection snapshot — that snapshot is dated 2026-07-30, does not
|
|
159
|
+
show these arguments, and would have confirmed the wrong answer. 104 commands were verified
|
|
160
|
+
clean. Every restored key is now pinned by a spec asserting on the OUTPUT of `build`, and three
|
|
161
|
+
of the affected classes had no spec file at all before this, which is a large part of how the
|
|
162
|
+
drift survived.
|
|
163
|
+
|
|
164
|
+
- **`Diff::Change` and the template-builder options DSL now carry an option's `value`.** Making
|
|
165
|
+
`value` required on `AddSelectFieldOption.build` exposed that two production paths never had one:
|
|
166
|
+
`Builder::TemplateBuilder#emit_options` and `Diff::CommandSynthesizer#option_command`. Neither had
|
|
167
|
+
ever been able to emit a valid `addSelectFieldOption`; the specs that passed were pinning a
|
|
168
|
+
command shape the server rejects. `VersionDiff#index_options` now captures `o['value']` alongside
|
|
169
|
+
label and weight — the field was already being fetched by the page-content fragment and thrown
|
|
170
|
+
away by the diff layer. Where no value is available, both paths **raise** naming the option and
|
|
171
|
+
field: `value` is documented as cast to a number for numeric select fields, so defaulting it to
|
|
172
|
+
the label would silently store wrong data on precisely the scored fields that matter.
|
|
173
|
+
|
|
174
|
+
- Corrected a false comment in `add_field.rb` asserting that a field's `required` flag "cannot be
|
|
175
|
+
persisted through the workflow command bus at all". It can, via `editFieldConfiguration`. A
|
|
176
|
+
comment stating a platform limitation that does not exist is worse than no comment: it stops
|
|
177
|
+
people trying.
|
|
178
|
+
|
|
179
|
+
### Removed
|
|
180
|
+
|
|
181
|
+
- `tools/template_yaml/ep_template_yaml.py` and `tools/template_yaml/mns_review.py` -- the
|
|
182
|
+
original Python template-backup projector and its cross-template audit. P9 of the template-yaml
|
|
183
|
+
Ruby port: the Ruby port (`model.rb`, `review.rb`, `update_gate.rb`, `render_markdown.rb`,
|
|
184
|
+
`cli.rb`) was proven byte/field-parity-identical to both by the P8 differential gate
|
|
185
|
+
(`differential_gate.rb`, 0 unexpected divergences over 18 live templates) before removal, and
|
|
186
|
+
the last remaining live use case -- a Jira ticket's YAML-only attachment (EPT-1872) -- was
|
|
187
|
+
re-verified against the promoted bridge (`yaml_to_raw_json.py`) with byte-identical
|
|
188
|
+
Python/Ruby deltas. Recoverable in full: `git show
|
|
189
|
+
0caa6f3d80c6495a9f92132178b9a6a42deb40f5:tools/template_yaml/ep_template_yaml.py` (and the same
|
|
190
|
+
path for `mns_review.py`).
|
|
191
|
+
|
|
192
|
+
## [2.1.0] - 2026-08-21
|
|
193
|
+
|
|
194
|
+
Everything accumulated on `main` since `v2.0.0` (2026-08-13): 150 commits touching 73 files under
|
|
195
|
+
`lib/`. **Minor, not patch:** the bulk is additive -- new data-field models, the last command-bus
|
|
196
|
+
command, a native people-directory query, template-change-log reading -- and 73 library files is not
|
|
197
|
+
a patch by any honest reading. **Minor, not major:** no surface was removed or reshaped, so `~> 2.0`
|
|
198
|
+
consumers adopt it without a floor change.
|
|
199
|
+
|
|
200
|
+
★ Why this release exists at all, beyond the contents: a remote clone installs PUBLISHED gems, so
|
|
201
|
+
until this went out none of that work could reach the api runner -- and `main` could not be released
|
|
202
|
+
either, because its version constant still read `2.0.0`, which `rake release:check` correctly refuses
|
|
203
|
+
as already published. Three weeks of library work with no route to a remote is the failure mode this
|
|
204
|
+
closes.
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
### Added
|
|
208
|
+
|
|
209
|
+
- **Wired the `manageCopyPageConfiguration` workflow command** (`Input::WorkflowCommand::ManageCopyPageConfiguration`,
|
|
210
|
+
first observed in the live schema 20260819): controls `overridePageCreatorPermissions`,
|
|
211
|
+
`autoIncludeNewContent`, and per-data-field `inclusionSettingsChanges` (`dataFieldId` /
|
|
212
|
+
`include` / `enforce`) for copy-page behaviour. Closes the last gap in the command bus --
|
|
213
|
+
`validate-queries` now reports 106/106 commands wired.
|
|
214
|
+
|
|
215
|
+
- `tools/mns/collection.rb` -- a pure-Ruby, stdlib-only read interface over the MnS Postman "ALL
|
|
216
|
+
CASES" master collection (the sibling `ep-api-collections` repo masters it; this gem never
|
|
217
|
+
hand-copies its knowledge). Walks the folder tree, exposes each GraphQL request's full path,
|
|
218
|
+
name, query, parsed variables, and `{{placeholder}}` inventory, with a name/path lookup that
|
|
219
|
+
tolerates a folder-path prefix and raises a named error listing near-matches when nothing
|
|
220
|
+
resolves. `spec/tools/mns/collection_sync_spec.rb` pins the webhook-admin and build/update-page
|
|
221
|
+
request paths plus the placeholders the tooling depends on, and fails -- naming exactly what
|
|
222
|
+
disappeared -- if the collection renames or removes one of them; it skips cleanly (not fails)
|
|
223
|
+
when no sibling checkout is present. See `tools/mns/README.md`.
|
|
224
|
+
|
|
225
|
+
- `tools/template_yaml/mns_review.py` -- cross-template audit over a directory of IR projections:
|
|
226
|
+
identifier coverage, `templateContainerUid` uniqueness and name plausibility, findings by code,
|
|
227
|
+
authoring-maturity signal, and classification of orphaned force bindings into projector gaps
|
|
228
|
+
versus real defects (checked against the source dumps). First run recorded in
|
|
229
|
+
`tools/template_yaml/reviews/2026-08-09-mns-18-templates.md`.
|
|
230
|
+
|
|
231
|
+
- **`tools/mns/cli.rb`** -- a Ruby CLI that creates/lists/destroys the M&S webhook
|
|
232
|
+
subscription and verifies the setup read-only, runnable from a support server with nothing
|
|
233
|
+
but `USER_EMAIL`/`USER_PASS` supplied (every other value defaults to the M&S UAT org, EU
|
|
234
|
+
instance). `webhook create` is idempotent in practice: it lists first and reports the
|
|
235
|
+
existing subscription instead of creating a duplicate when one already matches the URL and
|
|
236
|
+
template(s). `--dry-run` prints the GraphQL document and variables with no network call.
|
|
237
|
+
Document builders live in `tools/mns/webhooks.rb` (`MnsWebhooks::Documents`) as pure
|
|
238
|
+
functions, spec'd in `spec/tools/mns/webhooks_spec.rb` with no network involved.
|
|
239
|
+
|
|
240
|
+
- **`Query::PersonMembers`** — the GraphQL-native people-directory path over
|
|
241
|
+
`organization.personMembers`, filling the gap flagged in `model/organization.rb`. Salvaged
|
|
242
|
+
from a stranded July branch (`feat/scim-apiv0-adapter-design`) whose SCIM design and
|
|
243
|
+
scaffold were superseded by the `ecoportal-scim` gem's `apiv0-people-adapter` project; this
|
|
244
|
+
query was the only part of it with no equivalent anywhere. ★ It is NOT the SCIM-sourced
|
|
245
|
+
People replacement for the APIv0 retirement — that port lives in `ecoportal-scim`.
|
|
246
|
+
Reuses the existing `Base`/`Model`/`Connection::PersonMember` classes; no new models.
|
|
247
|
+
|
|
248
|
+
- `scripts/release_smoke_check.rb` — pre-push gate for BUILT gem artifacts (any gem in the
|
|
249
|
+
stack): packaging allowlist, byte corruption (`\r\r`, BOM, mixed EOL), and corruption-class
|
|
250
|
+
parse warnings via `ruby -wc`. Proven against real defects: red on eco-helpers 3.2.21
|
|
251
|
+
(shipped `\r\r\n`) and on the first 3.2.22 build (CHANGELOG `\r\r` via autocrlf smudge),
|
|
252
|
+
green on the corrected artifacts. Run it on every `.gem` before `gem push`.
|
|
253
|
+
|
|
254
|
+
- **Template change log now reports WHAT changed**, not only who/when/which-resource. New
|
|
255
|
+
registered fragment `:TemplateChangeLogEntryDetail`, opt-in via
|
|
256
|
+
`api.template.change_log(id:, first:, detail: true)` or
|
|
257
|
+
`&Query::TemplateChangeLog.detail_block`. The default selection is unchanged and still light —
|
|
258
|
+
the common "who touched this template and when" read does not pay for per-type detail.
|
|
259
|
+
`Base::Template::ChangeLogEntry` gains `#changes`, `#changeMessages`, `#detail_kind`
|
|
260
|
+
(`:changes` / `:change_messages` / `:es_changes` / nil) and `#detail?`.
|
|
261
|
+
★ The three concrete command types report changes in three different shapes, so `#changes`
|
|
262
|
+
returns raw hashes rather than a typed embed that would have to lie about one of them:
|
|
263
|
+
`PagesWorkflowCommandChange.changes` is `{field, from, to}` with STRING values;
|
|
264
|
+
`PagesWorkflowCommandEsChange.changes` has `from`/`to` as `StoredEsFilterType` OBJECTS (only
|
|
265
|
+
`field` is selected, so an ES change names which filter moved, not its before/after);
|
|
266
|
+
`PagesWorkflowCommandChangeMessage` carries pre-rendered `changeMessages` and no field/from/to.
|
|
267
|
+
Branch on `#detail_kind`. ★ Empty readers mean NOT SELECTED, never "nothing changed".
|
|
268
|
+
|
|
269
|
+
- **Template change log (GraphQL-native)** — `Query::TemplateChangeLog` reads the platform's
|
|
270
|
+
per-change audit log for a template: "for template X, who changed what and when", newest first,
|
|
271
|
+
paginated. Reachable as `api.template.change_log(id: template_page_id, first: 50)`, or bare
|
|
272
|
+
(`api.template.change_log.each(id: …)`) for an auto-paginating enumerator.
|
|
273
|
+
Read path: `currentOrganization.page(id:) → template → commands` — `template` is declared on
|
|
274
|
+
`BasePageInterface`, so it is selected through a type condition (selecting on the returned
|
|
275
|
+
`PageUnion` directly is invalid GraphQL). New supporting types:
|
|
276
|
+
`Base::Template::ChangeLogEntry`, `Model::Template::ChangeLogEntry` (adds the `owner` embed —
|
|
277
|
+
WHO changed it), `Connection::TemplateChangeLog`, and the registered fragment
|
|
278
|
+
`:TemplateChangeLogEntry` on the interface `PagesWorkflowCommandInterface`.
|
|
279
|
+
★ Two access caveats, both silent and both documented on `Base::Template::ChangeLogEntry`:
|
|
280
|
+
(1) the connection is **nil, not empty**, unless the caller satisfies
|
|
281
|
+
`Pages::TemplatePolicy#update_information?` — a read-only account sees no log and no error, so
|
|
282
|
+
never read nil as "nothing changed"; (2) the server scope is `from_template_builder`, so only
|
|
283
|
+
`TEMPLATE_BUILDER`-sourced commands appear — `WORKFLOW_BUILDER` changes to the same page are
|
|
284
|
+
excluded (those are on `Query::PagesWorkflowCommands`).
|
|
285
|
+
★ Why this beats polling a watermark: a forces run writes with `skip_patch_incr` + `timeless`,
|
|
286
|
+
bumping **neither `patchVer` nor `updatedAt`** — any watermark-polling change tracker is blind to
|
|
287
|
+
force-driven change, whereas the command log is per-change. (Open: whether forces run against
|
|
288
|
+
templates specifically is not confirmed.)
|
|
289
|
+
Also documented in `.ai-assistance/code/template_change_log.md`.
|
|
290
|
+
|
|
291
|
+
- **New tool `tools/template_yaml/delta.rb`** (P6 of the template-YAML-tooling Ruby port): the
|
|
292
|
+
deterministic before/after difference between two `project()` snapshots, shaped for the Rovo
|
|
293
|
+
delta-verification agent. Field pairing on id-then-identifier (so a REBUILT field -- new id,
|
|
294
|
+
same `description` -- is one `changed` entry rather than an add/remove pair), `TRACKED`-only
|
|
295
|
+
attribute diffing, force diffing by name with binding set-difference, the five-key template
|
|
296
|
+
diff, and the four `not_evaluable` strings reproduced VERBATIM, because the Rovo agent is
|
|
297
|
+
instructed to read that list literally and any wording drift changes what it is told it cannot
|
|
298
|
+
verify. **Verified against the canonical Python on the known pre/post pair (all 7 comparable
|
|
299
|
+
sections identical) and on 9 synthetic scenarios covering every branch -- rebuild, removal,
|
|
300
|
+
untracked-only change, template attributes, force add/remove/script/binding-set-diff, and
|
|
301
|
+
reference-id-only binding moves -- 0 mismatches.**
|
|
302
|
+
- **`Delta::Result` reports what the pairing could not say cleanly** -- colliding pairing keys,
|
|
303
|
+
duplicate force names (only the last is diffed), and rebuild pairings -- rather than returning
|
|
304
|
+
a bare hash the way the Python does. `review_findings` is **omitted** from the payload until a
|
|
305
|
+
reviewer is injected (it re-runs `review()`, which is P5): emitting an empty list there would
|
|
306
|
+
read as "no findings" when the truth is "not checked".
|
|
307
|
+
- **Corrected `P1-CONTRACT.md` section 8.** It claimed `_key` can return `None` and that fields
|
|
308
|
+
with neither id nor description are "filtered out of both snapshots entirely ... invisible to
|
|
309
|
+
`delta` by construction". Verified by running the Python: `'ref:' + ''` is truthy, so the
|
|
310
|
+
`or None` branch is unreachable and `_key` never returns `None`. Those fields are not filtered
|
|
311
|
+
out -- they all collapse onto the single key `'ref:'`, so an unidentified field in `before`
|
|
312
|
+
pairs with an **unrelated** unidentified field in `after` and their differences are reported as
|
|
313
|
+
a change. Not a live defect (every membrane in the JSON export carries a validated hex `_id`),
|
|
314
|
+
but a latent trap; the port reproduces it for parity and warns on it.
|
|
315
|
+
|
|
316
|
+
- **New tools `tools/template_yaml/field_walker.rb` + `tools/template_yaml/compare_fields.rb`**
|
|
317
|
+
(P3 of the template-YAML-tooling Ruby port): enumerates a template's fields in on-screen
|
|
318
|
+
LAYOUT order -- `flow_nodes` by `weight`, then `membrane_ids` / `left_membrane_ids` /
|
|
319
|
+
`right_membrane_ids`, then each id list in stored order -- porting the Python projector's
|
|
320
|
+
`walk_fields` against the contract frozen in `P1-CONTRACT.md`.
|
|
321
|
+
**Verified against the real 18-template M&S dump set: 2,714 fields, ids and ordering match the
|
|
322
|
+
Python projector exactly, with 0 unexpected divergences.** The only 6 differences are the
|
|
323
|
+
`ActionsList` ids the Python's YAML path corrupts (`6a4c4f12316577006e210b7a`..`..b7f`), where
|
|
324
|
+
the Ruby is correct and the Python is not; `compare_fields.rb` whitelists those six BY VALUE,
|
|
325
|
+
so a seventh divergence -- or any ordering defect on that same template -- still fails.
|
|
326
|
+
- **`FieldWalker` distinguishes "no fields" from "could not see the fields"**, which the Python
|
|
327
|
+
cannot: it returns a `Result` carrying the faithful field list plus every membrane it dropped,
|
|
328
|
+
every layout reference it could not resolve, duplicate placements, non-hash nodes and
|
|
329
|
+
defaulted weights, with `#blind?` true exactly when an empty list is untrustworthy. A
|
|
330
|
+
command-bus-built template with no layout, a `SplitSection` with no `dataFields`, and a
|
|
331
|
+
genuinely empty template all return an empty or short list from the Python with no error; they
|
|
332
|
+
are now told apart. Three port-critical quirks are preserved deliberately and covered by
|
|
333
|
+
specs: Python truthiness in the `or` chains (an empty `heading` must fall through to
|
|
334
|
+
`left_heading`, an empty `_type` must stay `''` -- `''` is truthy in Ruby), the STABLE node
|
|
335
|
+
sort (`Array#sort_by` is not stable), and `bool`-is-`int` weights.
|
|
336
|
+
|
|
337
|
+
- **New tools `tools/template_yaml/loader.rb` + `tools/template_yaml/id_guard.rb`** (P2 of the
|
|
338
|
+
template-YAML-tooling Ruby port): loads an ecoPortal template backup dump from its **JSON**
|
|
339
|
+
export -- not the YAML -- and validates every id-shaped value against `/\A[0-9a-f]{24}\z/`,
|
|
340
|
+
raising loudly (template, field path, offending value) rather than letting a bad id through.
|
|
341
|
+
Reading JSON instead of YAML is deliberate: the Python projector's YAML path decodes
|
|
342
|
+
`!ruby/object:BSON::ObjectId` via a step with a silent-failure mode (confirmed unchanged on
|
|
343
|
+
the canonical post-!86 surface in `P1-CONTRACT.md`) that corrupts 6 of 2,432 fields on one
|
|
344
|
+
M&S template without affecting counts. The JSON export carries identical data with plain hex
|
|
345
|
+
ids already, so the whole decode-bug class is structurally impossible on this path rather
|
|
346
|
+
than reimplemented. Verified against the real 18-template M&S JSON dump set, including the 6
|
|
347
|
+
previously-corrupted `ActionsList` ids on "Yard 5S Site Standard"
|
|
348
|
+
(`6a4c4f12316577006e210b7a`..`..b7f`), which load and validate correctly.
|
|
349
|
+
|
|
350
|
+
### Changed
|
|
351
|
+
|
|
352
|
+
- **`ecoportal-api-v2` floor raised to `>= 3.3.5`** (was `>= 3.3.3`). 3.3.5 carries the fix for
|
|
353
|
+
`ClassHelpers#to_time`, whose rescue clause named a constant that does not exist
|
|
354
|
+
(`ArgumentArgument`), so its documented `exception: false` mode raised
|
|
355
|
+
`NameError: uninitialized constant ...ClassHelpers::ArgumentArgument` instead of returning nil.
|
|
356
|
+
This gem inherits that helper through DoubleModel, so any null or object-shaped date reaching a
|
|
357
|
+
`passdate` field hit it. ★ Side benefit: the old floor pointed at **3.3.3, which was yanked**
|
|
358
|
+
for shipping internal repository content to rubygems — a floor should not name a yanked version.
|
|
359
|
+
|
|
360
|
+
### Fixed
|
|
361
|
+
|
|
362
|
+
- `FieldConfig::CrossReference` could not set `enableCrossRegisterReporting` (Boolean) — the schema
|
|
363
|
+
accepts the key but no builder path could reach it. Closes the last MISSING-key advisory reported
|
|
364
|
+
by `tests/validate_commands.rb` for the `crossReference` byType key.
|
|
365
|
+
|
|
366
|
+
- Stripped UTF-8 BOMs from 58 `lib/` source files (present since early development; harmless
|
|
367
|
+
to Ruby but flagged by the release smoke gate, and byte-noise for every downstream diff).
|
|
368
|
+
|
|
369
|
+
## [2.0.0] - 2026-08-13
|
|
370
|
+
|
|
371
|
+
Major release: everything accumulated on `main` since `v1.3.14` — the 2026-07-13/07-25/07-31
|
|
372
|
+
schema syncs, command-bus completion (105/105 commands), native file upload, and a long run of
|
|
373
|
+
correctness fixes. **Breaking, but narrowly:** every removed or reshaped surface either targeted
|
|
374
|
+
a mutation the live schema never had (so it could never have worked) or was a dead accessor with
|
|
375
|
+
no consumer — a 2026-07-30 sweep of `eco-helpers`, `integration-training`, `multi_org_api` and
|
|
376
|
+
`multi-org-idle` found no consumer of any breaking surface (re-confirmed 2026-08-12). The major
|
|
377
|
+
bump is deliberate: consumer repos declare `~> 1.3` (which allows 1.4.x), so a minor would have
|
|
378
|
+
been adopted silently on the next `bundle update`; 2.0.0 makes adoption a per-repo decision.
|
|
379
|
+
|
|
380
|
+
★ **What starts WORKING when you adopt this** (silently-broken → live, coming from ≤ 1.3.14):
|
|
381
|
+
the page-level `executeWorkflowCommands` bus, File-field attach writes, `updatePresetView`
|
|
382
|
+
column edits, AI-summary mutations, viewable-field management, Date-field renewals, and
|
|
383
|
+
eco-helpers' `OozeRedirect` force path (always errored before — re-verify on a sandbox org
|
|
384
|
+
before trusting it in a customer run). Review those paths before assuming a no-op upgrade.
|
|
385
|
+
|
|
386
|
+
Note: this release does not descend from `v1.3.15`, which shipped from the `release/1.3.15`
|
|
387
|
+
branch forked at 1.3.14 — do not expect a linear tag history.
|
|
388
|
+
|
|
389
|
+
★ **The published gem is now `lib/` only.** `spec.files` excluded just `test|spec|features`, so
|
|
390
|
+
every top-level directory added since shipped by default — 244 files of internal `.ai-assistance/`
|
|
391
|
+
notes, `docs/` (including the rolling worklog), and `.claude/`. `spec.files` is now an allowlist
|
|
392
|
+
(`lib/`, `exe/`, README, LICENSE, CHANGELOG), which also drops the package from 959 KB to 195 KB.
|
|
393
|
+
All 568 `lib/` files are unchanged; nothing outside `lib/` was ever loaded at runtime.
|
|
394
|
+
|
|
395
|
+
### Added
|
|
396
|
+
|
|
397
|
+
- `WorkflowCommandInput` commands: `editTemplateBasicSettings`, `editTemplateAdvancedSettings`,
|
|
398
|
+
`editTemplateCreatorPermissions`, `editTemplateDescriptions`, `createPublicConfig`,
|
|
399
|
+
`editPublicConfig`, `archivePublicConfig`, `addChecklistFieldItem`, `editChecklistFieldItem`,
|
|
400
|
+
`removeChecklistFieldItem`, `addSmartFillConfig`, `editSmartFillConfig`, `removeSmartFillConfig`.
|
|
401
|
+
- `addStage` gained `tags` (create a stage already tagged).
|
|
402
|
+
- `editFieldConfiguration` gained `addActionIds`/`removeActionIds`; `crossReference` gained
|
|
403
|
+
`addReferenceIds`/`removeReferenceIds`; `imageGallery` gained `addImageSourceIds`/`removeImageIds`;
|
|
404
|
+
new `file` by-type field config (`addFileContainerIds`/`removeItemIds`).
|
|
405
|
+
- **The WorkflowCommandInput command bus is now at full coverage: 105/105 commands, 14/14 field-config
|
|
406
|
+
builders, zero dead keys, zero unreachable keys** — verified against the live `20260731` schema.
|
|
407
|
+
Granular template management no longer has holes.
|
|
408
|
+
- **`tests/validate_commands.rb`** — new offline gate, the command-bus sibling of
|
|
409
|
+
`validate_queries.rb`. That gate can only see the documents we *send*; every command travels as a
|
|
410
|
+
member of a `[WorkflowCommandInput!]` **variable**, so unwired commands and stale key allow-lists
|
|
411
|
+
were completely invisible to it. The new script reports unwired commands, dead keys (gem sends,
|
|
412
|
+
schema rejects), orphaned `COMMAND_MAP` entries, missing keys, and byType builder coverage.
|
|
413
|
+
Fails the build on the first three. Wire it into CI next to `validate-queries`.
|
|
414
|
+
- **`addViewableField` / `moveViewableField` / `removeViewableField` commands** — these replaced
|
|
415
|
+
`WorkflowEditFieldConfigurationPeopleInput.addViewableFields`/`removeViewableFields`, which the
|
|
416
|
+
20260725 drift REMOVED. Between that drift and now, viewable-field management was impossible
|
|
417
|
+
through the gem: the old keys were dead and the new commands were unwired. The replacement also
|
|
418
|
+
adds ordering (`anchorId` + `anchorPosition`) the flat arrays could not express.
|
|
419
|
+
- **`Input::WorkflowCommand::EditFieldConfiguration::ActionList`** — the 14th and last unwired
|
|
420
|
+
`byType` member, so ActionsList field configuration is reachable at last.
|
|
421
|
+
- **`updateRelatedPage` mutation** + payload + `Builder::Template#update_related_page`. The worklog
|
|
422
|
+
carried this as an *ecoportal backend* gap ("the only genuine structural template omission") — that
|
|
423
|
+
was stale, the mutation is in the live schema, so the gap was ours. Related-pages entries could be
|
|
424
|
+
created and destroyed but never edited, forcing destroy+recreate for a title change, which
|
|
425
|
+
discards the entry id.
|
|
426
|
+
- **Cross-version template identity is now readable.** `CommonPageUnion` selects
|
|
427
|
+
`template { templateContainerUid active }`, and `Interface::BasePage` exposes `#template`
|
|
428
|
+
(a read-only `Model::Template::Information`) plus the `#templateContainerUid` shortcut.
|
|
429
|
+
`templateContainerUid` is the template **series** key: many versions may carry the same value,
|
|
430
|
+
but only one may be published (`active: true`) per organization at a time — publishing another
|
|
431
|
+
with the same uid unpublishes the incumbent. Previously the value was fetchable from the API but
|
|
432
|
+
unreachable through the gem (the embed was commented out and no fragment selected it).
|
|
433
|
+
Semantics documented in `.ai-assistance/code/ecoPortal_architecture/02_data_model.md`.
|
|
434
|
+
- **`editTemplateContainerUid` workflow command** — `Input::WorkflowCommand::EditTemplateContainerUid`,
|
|
435
|
+
registered on the command bus. Unlike its `editTemplate*` siblings it raises on a nil value rather
|
|
436
|
+
than emitting an empty command (the schema argument is `String!`) and validates the backend's
|
|
437
|
+
`3-20 chars, [a-zA-Z0-9-_.]` format up front.
|
|
438
|
+
- **DataField `description` is now readable.** Added to the `dataFieldInterface` fragment and
|
|
439
|
+
declared `read_only: true` on `Base::Page::DataField`. It is the hidden per-field note that
|
|
440
|
+
integrations reuse as a pseudo external-id on fields. Read-only is deliberate: `description`
|
|
441
|
+
exists on `DataFieldsInterface` but on no member of `DataFieldInput`, so a writable accessor would
|
|
442
|
+
dirty the field and push a key `updatePage` cannot accept — the only writer is the
|
|
443
|
+
`editFieldConfiguration` workflow command, which is confirmed to work on **page instances** as
|
|
444
|
+
well as templates.
|
|
445
|
+
- `tests/page_field_description_update.rb` — scripted read-modify-verify for a single dataField
|
|
446
|
+
`description` on a page instance, with a `--dry-run` mode and a `canRestructure`/`canConfigure`
|
|
447
|
+
pre-flight.
|
|
448
|
+
- **`Diff::Pairing::Signals.genome` now recognises lineage ancestry** (scores `0.9`, just below
|
|
449
|
+
an exact match) when one signature is a strict prefix of the other. Verified live 2026-08-05
|
|
450
|
+
on a same-org restore of a full template backup: a restore re-mints every Mongo id and
|
|
451
|
+
APPENDS one segment to every membrane AND force genome signature (28/28 + 4/4 followed the
|
|
452
|
+
rule, e.g. `ktnrya` → `ktnrya877l`) — equality-only scoring handed the exact cross-object
|
|
453
|
+
case the pairing engine exists for (UAT backup → PROD restore) a `0.0` mismatch. Signatures
|
|
454
|
+
shorter than 4 chars are rejected as ancestry evidence (chance-collision guard).
|
|
455
|
+
- **New manual tool `tests/template_backup_diff.rb`**: loads the platform's template BACKUP
|
|
456
|
+
files (YAML = Mongoid/BSON object dump — loaded via shims, no bson dependency; JSON = same
|
|
457
|
+
document, ids as hex/times as ISO8601), converts YAML→JSON, and produces an id-keyed deep
|
|
458
|
+
diff (adds/removes/changes/reorders, bookkeeping noise hidden by default, nil≡empty-container
|
|
459
|
+
lenience for document-age drift). Detects a foreign id-space and points at
|
|
460
|
+
`Diff::CrossObjectDiff` instead of emitting a misleading add/remove-everything report.
|
|
461
|
+
- Scoping project `.ai-assistance/projects/data-toolset/` — coordination of the data
|
|
462
|
+
import/extract/migration tool-set (legacy imports, template and register metadata table
|
|
463
|
+
definitions, BI warehouse extracts, spreadsheet and back-end imports, register-to-register and
|
|
464
|
+
org-to-org migrations, register-revamp mapping and readiness reporting). Capability map C1-C8,
|
|
465
|
+
verified inventory of existing tooling, the two shared primitives the set is missing (field
|
|
466
|
+
identity across template versions, and a versioned table projection), staged plan through to
|
|
467
|
+
promotion into its own repo, and the open blockers.
|
|
468
|
+
|
|
469
|
+
### Added (read-model / type layer — additive, non-breaking)
|
|
470
|
+
|
|
471
|
+
- **System access logs:** `Base::AuthLog` / `Model::AuthLog` (+ `Connection::AuthLog`, `:AuthLog`
|
|
472
|
+
fragment) and `Model::Organization#authLogs` (`Query::AuthLogs`).
|
|
473
|
+
- **Changelog history:** `Base::PersonMemberChangelog` / `Model::PersonMemberChangelog`
|
|
474
|
+
(+ `Connection::PersonMemberChangelog`, `:PersonMemberChangelog` fragment),
|
|
475
|
+
`Model::Organization#personMemberChangelogs` (`Query::PersonMemberChangelogs`), and
|
|
476
|
+
`Model::PersonMember#changelogs`.
|
|
477
|
+
- **Dashboards:** `Base::MinimalDashboard` / `Model::MinimalDashboard`
|
|
478
|
+
(+ `Connection::MinimalDashboard`, `:MinimalDashboard` fragment) and
|
|
479
|
+
`Model::Organization#dashboardSearch` (`Query::DashboardSearch`).
|
|
480
|
+
- **Actions:** `Base::ActionEvent` / `Model::ActionEvent` and `Base::ActionEventPage` /
|
|
481
|
+
`Model::ActionEventPage`.
|
|
482
|
+
- **RS/location:** read-only `LocationStructure#generating`/`#aiPrompt`,
|
|
483
|
+
`LocationClassificationType#aiGenerated` (selected in the structure queries + `:LocationNode`
|
|
484
|
+
fragment).
|
|
485
|
+
- **Contractor:** `updateContractorManagerSettings` mutation
|
|
486
|
+
(`Mutation::ContractorEntity::UpdateManagerSettings` + `Input`/`Payload::…::ManagerSettings`,
|
|
487
|
+
exposed as `Builder::ContractorEntity#update_manager_settings`) and read-only
|
|
488
|
+
`Organization#allowContractorAdminsToAddAdmins`.
|
|
489
|
+
- **`Base::AuthorizationResult` / `Model::AuthorizationResult`** (+ `:AuthorizationResult` fragment) —
|
|
490
|
+
the reusable node type behind the schema's many `canXXX: AuthorizationResult` permission fields;
|
|
491
|
+
wired `Model::PersonMember#canManageContractorAdmins`. Unblocks the deferred `Permissions`-parented
|
|
492
|
+
`canXXX` fields (which still await a `Permissions` model).
|
|
493
|
+
- **`Base::Permissions` / `Model::Permissions`** (+ `:Permissions` fragment) — the org-level ability
|
|
494
|
+
set (`Organization.permissions`). Models all **83** `canXXX: AuthorizationResult!` fields as
|
|
495
|
+
`embeds_one` (e.g. `dashboardCanManage`, `locationStructuresCanAiGenerateStructure`,
|
|
496
|
+
`generatedPageFilterCanUseSmartQuery`). Wired `Model::Organization#permissions` (typed embed) plus a
|
|
497
|
+
native `Query::Permissions` (`currentOrganization.permissions`). The `:Permissions` fragment spreads
|
|
498
|
+
`:AuthorizationResult` per field (recursively assembled).
|
|
499
|
+
|
|
500
|
+
### Added (polymorphic activity feeds — the REAL access-logs & page-history fields)
|
|
501
|
+
|
|
502
|
+
The web "System Access Logs" page and page "history changelog" are driven by
|
|
503
|
+
`currentOrganization.activityLogs` (a UNION) and `page.activities` (an INTERFACE) — NOT the flat
|
|
504
|
+
`authLogs`/`personMemberChangelogs` types. These add the polymorphic read models for the real fields.
|
|
505
|
+
|
|
506
|
+
- **System Access Logs:** `Base::ActivityLog` / `Model::ActivityLog` (+ nested `Model::ActivityLog::Resource`,
|
|
507
|
+
`Connection::ActivityLog`, `:ActivityLog` fragment) over the `ActivityLogUnion` (9 members:
|
|
508
|
+
DashboardAccess/Create/Delete/Update, DeniedDashboardAccess, DeniedPageAccess, FileDownload, PageAccess,
|
|
509
|
+
ScimIntegrationAccess). Models the fields common to all members + `__typename` passthrough; the Dashboard*
|
|
510
|
+
members' `parentResource*` + `resource { isVisible: AuthorizationResult }` are nullable embeds. The
|
|
511
|
+
fragment uses inline fragments per member (spreading `:ActivityLogCommon` on `BaseActivityLogInterface`
|
|
512
|
+
and `:ActivityLogResource` on `BaseDashboardActivityLogInterface`). Exposed as
|
|
513
|
+
`Model::Organization#activityLogs` (`Query::ActivityLogs`) with the full filter set
|
|
514
|
+
(`userIds`, `resourceIds`, `filterSuperusers`, `activityType`, `resourceType: ActivityLogTypesEnum`,
|
|
515
|
+
`source: SourceEnum`, `dateFilter: DateRange`, cursor pagination). New `Input::DateRange`.
|
|
516
|
+
- **Page history / activities:** `Base::Activity` / `Model::Activity` (+ `Connection::Activity`,
|
|
517
|
+
`:Activity` fragment) capturing the `ActivityInterface` common fields (id, `__typename`, priority,
|
|
518
|
+
system, fromPublicTemplate, stageId, categories/subkey, source/user scalars, createdAt/updatedAt,
|
|
519
|
+
personMember, user) across its ~61 concrete types — an unmodelled type still resolves as a plain
|
|
520
|
+
`Model::Activity`. Exposed as `Model::Organization#pageActivities` (`Query::PageActivities`) resolving
|
|
521
|
+
`page(id:).activities(searchConf:, …)`; because `page` returns a `PageUnion`, the connection is selected
|
|
522
|
+
via inline fragments on BasicPage/PhasedPage (`:PageActivities` + `:ActivityConnection` fragments).
|
|
523
|
+
|
|
524
|
+
### Changed
|
|
525
|
+
|
|
526
|
+
- `ecoportal-api` dependency floor raised to `0.10.17`: inherits the `WithRetry` fix that
|
|
527
|
+
makes `HTTP::TimeoutError` (connect/read/write timeouts) retryable — previously a single
|
|
528
|
+
transient timeout killed whole batch loops (live-confirmed on Farmers, 2026-07-30).
|
|
529
|
+
- **`graphlient` dependency now points at the published `0.9.0` release** instead of the fork's
|
|
530
|
+
frozen git branch (`rellampec/graphlient@pre-v0.0.9`). `0.9.0` ships the same DSL/directive
|
|
531
|
+
work the gem already relied on (`#115` `to_query_string`/`spread`, `#116` directives DSL,
|
|
532
|
+
`spread(on:)` inline fragments, `fragment(:Name, on:)`, custom scalar registration) — non-breaking,
|
|
533
|
+
since the gem's own usage of these APIs is unchanged. `Gemfile` git override removed;
|
|
534
|
+
`ecoportal-api-graphql.gemspec` bound updated `>= 0.8.0, < 0.9` → `>= 0.9.0, < 0.10`.
|
|
535
|
+
|
|
536
|
+
### Changed (BREAKING)
|
|
537
|
+
|
|
538
|
+
- `reorderForces` and `reorderSection`: `after`/`before` replaced by `anchorId`/`anchorPosition`.
|
|
539
|
+
- `moveField`: gained `anchorId`/`anchorPosition`.
|
|
540
|
+
- SmartFill removed from `date`/`plainText`/`richText`/`select` field configs — moved to the
|
|
541
|
+
dedicated `*SmartFillConfig` commands above.
|
|
542
|
+
- **AI summary mutations rewired to the fields that actually exist.** Both targeted mutation names
|
|
543
|
+
that are absent from every introspection we hold (2026-07-13 and 2026-07-30), so neither ever
|
|
544
|
+
worked:
|
|
545
|
+
- `Mutation::AiSummary::Generate`: `generateAiSummary(pageId:, stageId:)` →
|
|
546
|
+
**`generatePageSummary(input: GenerateInput!)`**. `#query` now takes `page_id:` / `stage_id:`
|
|
547
|
+
(was `pageId:` / `stageId:`) and wraps them into `input`.
|
|
548
|
+
- `Mutation::AiSummary::SubmitFeedback`: `submitAiSummaryFeedback(aiSummaryVersionId:, sentiment:)`
|
|
549
|
+
→ **`submitPageAiSummaryFeedback(input: SubmitFeedbackInput!)`**. `#query` takes
|
|
550
|
+
`ai_summary_version_id:` / `sentiment:`. The enum is `SentimentEnum`, not
|
|
551
|
+
`AiSummarySentimentEnum`, and its values are **`positive` / `negative`** — the class previously
|
|
552
|
+
documented "THUMBS_UP"/"THUMBS_DOWN", which the schema has never accepted. `#query` validates
|
|
553
|
+
the value up front.
|
|
554
|
+
- `Base::AiSummaryVersion` dropped `prompt`, `inputTokens`, `outputTokens`, `totalTokens`,
|
|
555
|
+
`resourceType`, `ratings` — none exist on the type; they always read nil. Real fields:
|
|
556
|
+
`aiSummary`, `alreadyRated`, `createdAt`, `dataFieldLogs`, `generationErrors`, `id`,
|
|
557
|
+
`pagePatchVer`, `status` (the last three complex ones stay unmodelled until verified).
|
|
558
|
+
|
|
559
|
+
_(The `Payload::OkPayload` errors-modelling fix from the same commit is NOT breaking and
|
|
560
|
+
already shipped in 1.3.15 — see that release's section.)_
|
|
561
|
+
- **`FileUpload::Client` reimplemented natively from a captured web upload** (breaking, but the
|
|
562
|
+
old path could not work). The real flow — verified from a HAR of the React frontend on
|
|
563
|
+
2026-07-30, then cross-checked against the live schema — is three steps, all GraphQL except
|
|
564
|
+
the storage POST:
|
|
565
|
+
1. `FileSignature` (GraphQL) → presigned policy + credentials
|
|
566
|
+
2. multipart POST to S3 → `204`; fields in order: `key`, `AWSAccessKeyId`, `policy`,
|
|
567
|
+
`signature`, `content-type`, `x-amz-server-side-encryption`, `file`
|
|
568
|
+
3. **`uploadFile` (GraphQL)** → the `FileContainer`, whose `id` page mutations consume
|
|
569
|
+
|
|
570
|
+
The previous implementation was a port of `ecoportal-api-v2`'s REST S3 code and did
|
|
571
|
+
`POST /api/v2/<org>/s3/files` + polling. **The platform does not use those endpoints for this
|
|
572
|
+
flow** — there is no register-over-REST and no poll — so the 1.3.15 change that made those
|
|
573
|
+
calls authenticate (`X-ECOPORTAL-API-KEY`) fixed a step that does not exist. No API key is
|
|
574
|
+
needed for file upload at all; `api_key:` on `GraphQL.new` remains available but unused here.
|
|
575
|
+
- **New:** `Mutation::FileContainer::Upload` (`uploadFile`), `Payload::Upload`, and
|
|
576
|
+
`Concerns::Threadable` (bounded concurrency, ported from `ecoportal-api-v2` rather than
|
|
577
|
+
depended on, since that gem is being decommissioned).
|
|
578
|
+
- **New: `#upload_all(paths, threads: 4) { |result| }`** — concurrent multi-file upload with
|
|
579
|
+
per-file error isolation (a single failure never raises out of the batch; each `Result`
|
|
580
|
+
carries its own `error`/`container_id`), presigning **once** per batch, and a `Result` struct
|
|
581
|
+
shaped like v2's `S3::Files::BatchUpload::FileResult`. `threads: 1` runs inline.
|
|
582
|
+
- **New: stage hooks** — `client.on(:signature|:storage|:register) { … }`, chainable, for
|
|
583
|
+
logging/instrumentation/middleware around each step.
|
|
584
|
+
- **Fixed: storage keys no longer collide.** The key is
|
|
585
|
+
`uploads/<userId>/<epoch-ms>-<token>-/<basename>` as the web client builds it; the old
|
|
586
|
+
`upload_prefix + filename` concatenation meant two uploads of `report.pdf` overwrote each
|
|
587
|
+
other in the bucket.
|
|
588
|
+
- **Fixed: `x-amz-server-side-encryption` is read from the policy** (base64 JSON `conditions`)
|
|
589
|
+
instead of being hardcoded to `AES256` — the value now comes from the same source S3 validates
|
|
590
|
+
against, with `AES256` only as a fallback.
|
|
591
|
+
- **Fixed: `Base::FileContainer`** declared `activeVersionId`, which does not exist on the type
|
|
592
|
+
(it is `activeVersion`) and always read nil; `otherTags` was missing, which matters because
|
|
593
|
+
`UploadInput.otherTags` is the only way to tag a container — now exposed as
|
|
594
|
+
`upload(path, tags: […])`.
|
|
6
595
|
|
|
7
596
|
### Fixed
|
|
8
597
|
|
|
9
|
-
-
|
|
10
|
-
|
|
11
|
-
`
|
|
12
|
-
|
|
13
|
-
|
|
598
|
+
- **Cascaded leaf arrays are no longer dropped from `as_update`.** Leaf arrays declared with
|
|
599
|
+
`passarray`/embeds-many (id-lists, tag-lists, config-lists) were invisible to the diff: the
|
|
600
|
+
default `DiffService` strips cascaded keys from the flat classic diff, and `diff_reduce` only
|
|
601
|
+
re-adds children that are a `GraphQL::Model` — an `ArrayModel`/`CollectionModel` is not — so
|
|
602
|
+
the array change was silently discarded and no mutation was issued for it (SYNTHESIS.md 3.1).
|
|
603
|
+
The `DataField`-local `LeafDiffService` is promoted to the common layer
|
|
604
|
+
(`common/graphql/model/diffable/leaf_diff_service.rb`): it keeps cascaded doc keys in the flat
|
|
605
|
+
diff, preserves the flat-diff placeholder for non-model leaf children while still cascading
|
|
606
|
+
into real nested models and dropping `root!` children, and treats a leaf array as an opaque
|
|
607
|
+
full-set replace (no id-keyed nested patch-ops), matching how the write inputs consume these
|
|
608
|
+
arrays. Set as `DIFF_CLASS` on `Interface::BasePage` (covers Basic + Phased), `Base::Register`
|
|
609
|
+
and `Base::PresetView`; `Base::Page::DataField` now references the promoted class with
|
|
610
|
+
identical behaviour. Newly detected: page `otherTags` (full-set replace) and `locations`
|
|
611
|
+
(`[{id:}]` via `location_ids=`), `Register#filterTags`, and `PresetView#fieldConfigurations`.
|
|
612
|
+
- `Base::PresetView` now emits a schema-valid `updatePresetView` input for its column
|
|
613
|
+
configuration. The read model exposes the collection as `fieldConfigurations` (the key the
|
|
614
|
+
API returns), but `UpdatePresetViewInput` calls it `fieldConfigs` **and** takes it as a
|
|
615
|
+
`FieldConfigurationOneToManyInput` — `{ additions:, deletions:, updates: }` — not as the
|
|
616
|
+
read list; both facts are schema-confirmed in the live introspection dump (20260730), where
|
|
617
|
+
the field is also NON_NULL with no default, i.e. required on every call. Emitting the read
|
|
618
|
+
key would be an unknown-argument error and emitting the read list under the write key would
|
|
619
|
+
be a type error, either of which rejects the WHOLE mutation, a `name`-only edit included.
|
|
620
|
+
`#as_input` (and `Input::PresetView::Update.from_model`, which shares the same reshape, so
|
|
621
|
+
the implicit and explicit converter seams agree) now renames the key, computes the
|
|
622
|
+
additions/deletions/updates delta directly from `doc` vs `original_doc` — matching configs on
|
|
623
|
+
their `id` and whitelisting the fields `FieldConfigurationInput` accepts, so the read-only
|
|
624
|
+
`__typename` is dropped — and always sets `fieldConfigs`, using the no-op `{}` when the
|
|
625
|
+
columns did not change. A columns-only change is now sent at all: it was previously dropped
|
|
626
|
+
from the flat diff, so `as_input` returned `nil` and no mutation was issued.
|
|
627
|
+
`Input::PresetView::Update` declared `fieldConfigs` as a `passarray`; it is now a
|
|
628
|
+
`passthrough`, matching the object the schema expects. The create path is unaffected —
|
|
629
|
+
`CreatePresetViewInput.fieldConfigs` is a plain `[FieldConfigurationInput!]!` and
|
|
630
|
+
`Input::PresetView::Create` already used the write key with the right shape.
|
|
631
|
+
- `Base::Page::DataField::FileField` now reads and writes the shape the live API actually
|
|
632
|
+
uses. WRITE: `as_input` emits `file: { id:, items: [ItemInput] }` — live `FileInput` has
|
|
633
|
+
no `fileContainerIds` member, so every File-field write was rejected (live-confirmed
|
|
634
|
+
2026-08-01 via `pages/file_upload`; the 4-step upload passed, the attach failed). The
|
|
635
|
+
backend applies `items` as full-replace (any existing item id not echoed back is
|
|
636
|
+
destroyed), so kept containers are sent as `{ id: <item_id> }` and new ones as
|
|
637
|
+
`{ fileContainerId: }`. READ: `file_container_ids` now maps `items[].fileContainer.id`
|
|
638
|
+
(the fragment's actual selection, which now also selects the item `id`) instead of a
|
|
639
|
+
`fileContainers` doc key the API never returns — reads always came back empty before.
|
|
640
|
+
BREAKING (dead surface): the `FileField#fileContainers` accessor is gone, replaced by
|
|
641
|
+
`items`; no consumer existed in this gem or eco-helpers, and it could only ever return
|
|
642
|
+
empty against real API responses. `file_container_ids` / `file_container_ids=` keep
|
|
643
|
+
their contract. `ImageGallery` is untouched: its write shape is also invalid, but live
|
|
644
|
+
`ImageInput` attaches via `sourceId` (an `Enzyme::ImageReference::TempImage`, a
|
|
645
|
+
different upload pipeline than file containers) — needs its own design, tracked in the
|
|
646
|
+
DataField shape-asymmetry review.
|
|
647
|
+
- **`People#dirty?`** compares the people-id SET vs `original_doc` (falling back to the
|
|
648
|
+
`people{id}` nodes on both sides), not the raw `peopleIds` key — the backend can return
|
|
649
|
+
`peopleIds: null` on reads while still populating `people`/`cachedPeople`, so restating an
|
|
650
|
+
already-attached person id no longer registers as a change. Live-confirmed 2026-07-16
|
|
651
|
+
(act-gov TOOCS dry-run reported "Updated 6/6" for a no-op). Mirrors the `CrossReference`
|
|
652
|
+
fix for the identical disease; `as_input` now serialises the fallback-aware `people_ids`
|
|
653
|
+
reader instead of the raw doc key.
|
|
654
|
+
- `ContractorEntities` field: the reader read the staged write key (`contractors`), which read
|
|
655
|
+
responses never populate — so it always returned `[]` on a freshly-fetched page — and the
|
|
656
|
+
default leaf diff phantom-dirtied the field the moment any setter ran, even for a no-op
|
|
657
|
+
restatement or a clear on an already-empty field. Now reads `contractorEntities[].id` with
|
|
658
|
+
staged-write preference and compares effective id SETS against `original_doc` in `dirty?`
|
|
659
|
+
(the CrossReference fix template).
|
|
660
|
+
- `Query::Page` now accepts the `CommonPageUnion` document variables (`showHiddenData`,
|
|
661
|
+
`content`, `only_content`, `fields`) as call params, and `Compat::Pages#get` forwards
|
|
662
|
+
them (`pages.get(id, content: false)`). Previously `accepted_params :id` silently
|
|
663
|
+
dropped any override, so the document-level defaults could never be changed.
|
|
664
|
+
This matters for least-privilege accounts: `attachedFiles @include(if: $content)` is
|
|
665
|
+
preauthorized on the `files: download` ability, so an account without that grant could
|
|
666
|
+
not complete **any** page read — found live when the template-tests account
|
|
667
|
+
(`-space graphql_templates`) had every `pages.get` refused while a minimal hand-written
|
|
668
|
+
page query succeeded. `content: false` is the structure-only read (template tooling,
|
|
669
|
+
config audits) and needs no file grant. Defaults are unchanged — no caller impact.
|
|
670
|
+
- **Four `Input::LocationStructure` command bugs are fixed — `add(type, **kwargs)` was broken on
|
|
671
|
+
every path.** `UpdateCommand#name` / `#classificationIds` called a non-existent `super` (plus a
|
|
672
|
+
redundant `nil.empty?` guard), raising `NoMethodError`; both readers now fall back to the stored
|
|
673
|
+
`name` / `classificationIds` so they work with or without a `new*` override. `ApplyCommands` and
|
|
674
|
+
`Draft::AddCommands` mapped the `:reorder` command type through a typo'd `:reoder` key, so
|
|
675
|
+
`add(:reorder, ...)` raised `NameError: uninitialized constant ...::ReoderCommand` — reorder was
|
|
676
|
+
unreachable from either dispatcher. `Interface::LocationStructure::Command#set_values` called the
|
|
677
|
+
0-arg reader instead of the writer (`#{key}=`), raising `ArgumentError` and breaking the whole
|
|
678
|
+
`#add` path for every command type, not only reorder. Adds `commands_mapping_spec` (18 examples)
|
|
679
|
+
covering all four. Note: the typo symbol `:reoder` is no longer in the dispatch table, so
|
|
680
|
+
`add(:reoder)` now raises `RuntimeError: Unknown command type: 'reoder'` instead of `NameError` —
|
|
681
|
+
not a breaking change, since `:reoder` never resolved to a real class either way.
|
|
682
|
+
- **`FieldConfig::People` sent two keys the server rejects** — `addViewableFields` /
|
|
683
|
+
`removeViewableFields`, removed from the schema in the 20260725 drift. Now dropped, and the six
|
|
684
|
+
keys that drift *added* are reachable: `add`/`removeAllowedUserGroupIds`,
|
|
685
|
+
`attachedPeoplePermissionsEnabled`/`Editable`/`Flags`, `applyAttachedPeoplePermissionsTo`. The
|
|
686
|
+
nested flags hash is filtered to the seven declared flags so a stray key cannot sink the command.
|
|
687
|
+
- **`FieldConfig::Date` could not set renewals** — `createEvent`, `remindMeIn`, `renews`,
|
|
688
|
+
`renewsEvery`, `renewsUnit`, `renewsUntil` were all unreachable. Renewals are how expiry-driven
|
|
689
|
+
registers (certifications, inductions, permits) are configured, so this was a functional hole
|
|
690
|
+
rather than a cosmetic one.
|
|
691
|
+
- **`EditFieldConfiguration` silently dropped `stageId`** — required to disambiguate a field on a
|
|
692
|
+
phased page, which made the builder unusable there; callers had to hand-build the command hash.
|
|
693
|
+
`addPermittedPersonSchemaIds` / `removePermittedPersonSchemaIds` were dropped the same way.
|
|
694
|
+
- **Connection node-type poisoning.** `Logic::Connection` declared `embeds_many :nodes, klass: :node_class`
|
|
695
|
+
on the shared base, so the v2 collection layer memoized the first-resolved node class onto the single
|
|
696
|
+
shared collection — the first connection instantiated in a process poisoned every other connection's
|
|
697
|
+
instance `nodes` typing (e.g. a `MinimalDashboard` connection returning `AuthLog` nodes), corrupting
|
|
698
|
+
`QueryConnection#each` pagination when >1 connection type is used per process. Each subclass now binds
|
|
699
|
+
its own concrete-class collection via the new `Logic::Connection.nodes_of` macro. Regression spec added.
|
|
700
|
+
- `Compat::Response` now validates at construction that its payload honours the response contract
|
|
701
|
+
(`success?`/`error?`/`error_doc`/`item`), raising `ArgumentError` with the missing methods
|
|
702
|
+
otherwise. Closes the duck-typing drift class behind the eco-helpers 3.2.19 KPI-counter
|
|
703
|
+
regression (a non-response object slipping through). +spec `spec/ecoportal/api/graphql/compat/response_spec.rb`.
|
|
704
|
+
- **`main`'s version constant no longer advertises a published release it is not.** `2dad1e4`
|
|
705
|
+
(2026-08-08) set `GRAPQL_VERSION` to `1.3.15` while raising the `ecoportal-api` floor to
|
|
706
|
+
`0.10.17`. But `1.3.15` had already shipped nine days earlier from `release/1.3.15` (tag
|
|
707
|
+
`v1.3.15`, on RubyGems since 2026-07-30), and that tag is **not** an ancestor of `main` — the
|
|
708
|
+
two lines forked at `21516a3` (1.3.14) and `main` has carried ~200 commits of 1.4.0-track work
|
|
709
|
+
since. So `main` was building a materially different tree under a published version number,
|
|
710
|
+
against this repo's "never ship a fix under a published version" convention. The constant was
|
|
711
|
+
restored to `1.3.14` — the last release `main`'s tree actually descends from — until this
|
|
712
|
+
release set it to `2.0.0`. The `0.10.17` floor itself is unaffected and ships with this release.
|
|
713
|
+
|
|
714
|
+
### Removed (BREAKING)
|
|
715
|
+
|
|
716
|
+
- `WorkflowCommandInput` commands `editPage` and `editPageCreatorPermissions` — removed from the
|
|
717
|
+
live schema (2026-07-13) and now removed from the gem. `WorkflowCommand.build(:editPage, …)` /
|
|
718
|
+
`build(:editPageCreatorPermissions, …)` raise `ArgumentError` (unknown key). The
|
|
719
|
+
`DEPRECATED_KEYS` / `warn_deprecated` machinery on `Input::WorkflowCommand` was removed with them.
|
|
720
|
+
**Migrate to:** `editTemplateBasicSettings` (name/icon/settings/counter/tags/folders/creator
|
|
721
|
+
perms), `editTemplateDescriptions` (`description`), `editTemplateCreatorPermissions` (creator
|
|
722
|
+
perms). The old `editPage` `addOtherTags`/`removeOtherTags` keys have no `editTemplate*`
|
|
723
|
+
equivalent (dropped from schema). No downstream callers existed (eco-helpers / multi_org_api /
|
|
724
|
+
gem swept) so the removal is clean. See DECISIONS.md in the workflow-space project.
|
|
725
|
+
- **`Mutation::SmartFill::Generate` / `Mutation::SmartFill::SubmitFeedback` and
|
|
726
|
+
`Builder::Page#generate_smart_fill` / `#submit_smart_fill_feedback`** (breaking, but dead
|
|
727
|
+
code) — `smartFillGenerate` and `smartFillSubmitFeedback` **do not exist in the schema**, and
|
|
728
|
+
never did: the live mutation list has no `*fill*` mutation at all (checked against both the
|
|
729
|
+
2026-07-13 and 2026-07-30 introspections). SmartFill exists only as *configuration*
|
|
730
|
+
(`WorkflowCommandInput`'s `add/edit/removeSmartFillConfig`, the `SmartFill*Configuration`
|
|
731
|
+
types) and as a **read** data field — `Base::Page::DataField::SmartFill` is unaffected and
|
|
732
|
+
stays. Nothing could have depended on the removed mutations because they always failed; if
|
|
733
|
+
page-level SmartFill triggering is needed, it has to be added to the platform first.
|
|
734
|
+
|
|
735
|
+
### Documentation
|
|
736
|
+
|
|
737
|
+
- `ecoPortal_architecture/10_forces_workflow_builder.md`: operational rules for auditing force
|
|
738
|
+
bindings — a binding may target a field OR a section; `globalBindings` is a separate collection;
|
|
739
|
+
a field declaring `global_binding` is present at stage render regardless of its section/stage;
|
|
740
|
+
backup-YAML ObjectIds are binary so a text search for an id proves nothing.
|
|
741
|
+
- `ecoPortal_architecture/07_data_fields.md`: which subset of fields carries an identifier, and how
|
|
742
|
+
to measure coverage — only the QUESTION carries one; its satellites (comment, image, document,
|
|
743
|
+
recommended action) do not and are not expected to. The denominator is workbook questions
|
|
744
|
+
(`question_ref`), never the field count; measuring against all fields yields a meaningless ~16%.
|
|
745
|
+
- `.ai-assistance/projects/mns-template-lifecycle/WORKBOOK-FIELD-MAPPING.md` — the authoritative
|
|
746
|
+
workbook-to-template contract recovered verbatim from the 2026-08-08 session transcript:
|
|
747
|
+
`QuestionSetReference` → template_container_id (UI "UNIQUE IDENTIFIER"), `QuestionReference` →
|
|
748
|
+
field `description` (CONFIRMED), `QuestionInformation` → field tooltip (strip HTML entities),
|
|
749
|
+
scores ignored, section-vs-stage left ambiguous, plus the template-pairing procedure and the
|
|
750
|
+
DEV-site targeting note.
|
|
751
|
+
- `.ai-assistance/conventions/recovering-prior-context.md` — past sessions are greppable JSONL
|
|
752
|
+
transcripts on disk (35 sessions, 85 MB); search them before asking the developer something he may
|
|
753
|
+
already have answered.
|
|
14
754
|
|
|
15
755
|
## [1.3.15] - 2026-07-30
|
|
16
756
|
|